zoukankan      html  css  js  c++  java
  • 陈丹琪分治

    http://wenku.baidu.com/link?url=Nq_9vn-F1a8xOarR8XVdGVzMISDDQETGRU2-5q9moFr8SVqLhsOcDgUDMfCR_994pNiHtYFoK0lTe0BXnl4tNIc-UWas7VnIvvfE8hw8UwO

    cdq提出的一种分治手段。

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88335#problem/B

    题意,+ a b操作是增加一个线段【a,b】,?c d 是询问此前有多少个线段满足a<=c<d<=b

    暴力n^2

    如果所有的查询都在增加线段之后,我们可以把线段和查询都按照左端点从小到大排序,然后单调队列两个指针。当线段左端点a<=查询c的时候,线段指针后移,并将线段的右端点加入树状数组中,当遇到a>c的时候,说明此后的线段都不满足了,这个查询的答案就是树状数组中y》=d的个数,可以用sum(MAX)-sum(y-1)得出,复杂度logn,然后查询的指针后移一个,这样每个查询和每个线段都只会走一次,总体复杂度nlogn。类似离线的查询。

    但是这个题目中插入和查询的穿插出现的,就是在线的查询,通过cdq分治就可以转换为上述离线的查询。

    分治思想是解决上述问题定义为solve(l,r),答案就是solve(1,n)

    每次将区间等分为l到mid,mid+1到r

    左区间的+都可以对右区间的?产生贡献,并且时间上都早于右边的查询,因此可以利用上诉离线算法在nlogn内完成,

    然后递归解决左右区间内部的问题。logn。

    总体复杂度n*log(n)*log(n)

      1 //#define debug
      2 //#define txtout
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<cctype>
      8 #include<ctime>
      9 #include<iostream>
     10 #include<algorithm>
     11 #include<vector>
     12 #include<queue>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #define mt(a,b) memset(a,b,sizeof(a))
     17 using namespace std;
     18 typedef long long LL;
     19 const double eps=1e-8;
     20 const double pi=acos(-1.0);
     21 const int inf=0x3f3f3f3f;
     22 const int M=5e5+10;
     23 struct G {
     24     char op[4];
     25     int x,y,id;
     26     friend bool operator <(const G &a,const G &b){
     27         return a.x<b.x;
     28     }
     29 } g[M];
     30 vector<int> a;
     31 vector<G> p,q;
     32 map<int,int> mp;
     33 int res[M];
     34 class One_Tree_Array { //一维树状数组
     35     typedef int typev;
     36     typev a[M];
     37 public:
     38     void init() {
     39         mt(a,0);
     40     }
     41     int lowb(int t) {
     42         return t&(-t);
     43     }
     44     void add(int i,typev v) {
     45         for(; i<M; a[i]+=v,i+=lowb(i));
     46     }
     47     typev sum(int i) {
     48         typev s=0;
     49         for(; i>0; s+=a[i],i-=lowb(i));
     50         return s;
     51     }
     52 }tree;
     53 int bigy;
     54 void cdq(int L,int R) {
     55     if(L==R) return ;
     56     int mid=(L+R)>>1;
     57     p.clear();
     58     for(int i=L; i<=mid; i++) {
     59         if(g[i].op[0]=='?') continue;
     60         p.push_back(g[i]);
     61     }
     62     q.clear();
     63     for(int i=mid+1; i<=R; i++) {
     64         if(g[i].op[0]=='+') continue;
     65         q.push_back(g[i]);
     66     }
     67     sort(p.begin(),p.end());
     68     sort(q.begin(),q.end());
     69     int lp=p.size();
     70     int lq=q.size();
     71     int len=0;
     72     for(int i=0,j=0;i<lq;i++){
     73         while(j<lp&&p[j].x<=q[i].x){
     74             tree.add(p[j].y,1);
     75             j++;
     76             len=j;
     77         }
     78         res[q[i].id]+=tree.sum(bigy)-tree.sum(q[i].y-1);
     79     }
     80     for(int i=0;i<len;i++){
     81         tree.add(p[i].y,-1);
     82     }
     83     cdq(L,mid);
     84     cdq(mid+1,R);
     85 }
     86 int main() {
     87 #ifdef txtout
     88     freopen("in.txt","r",stdin);
     89     freopen("out.txt","w",stdout);
     90 #endif
     91     int n;
     92     while(~scanf("%d",&n)) {
     93         a.clear();
     94         for(int i=1; i<=n; i++) {
     95             scanf("%s%d%d",g[i].op,&g[i].x,&g[i].y);
     96 //            a.push_back(g[i].x);
     97             a.push_back(g[i].y);
     98         }
     99         sort(a.begin(),a.end());
    100         int la=unique(a.begin(),a.end())-a.begin();
    101         mp.clear();
    102         for(int i=0; i<la; i++) {
    103             mp[a[i]]=i+1;
    104         }
    105         bigy=0;
    106         for(int i=1; i<=n; i++) {
    107 //            g[i].x=mp[g[i].x];
    108             g[i].y=mp[g[i].y];
    109             bigy=max(bigy,g[i].y);
    110             g[i].id=i;
    111             res[i]=0;
    112         }
    113         tree.init();
    114         cdq(1,n);
    115         for(int i=1; i<=n; i++) {
    116             if(g[i].op[0]=='+') continue;
    117             printf("%d
    ",res[i]);
    118         }
    119     }
    120     return 0;
    121 }
    View Code

    end

  • 相关阅读:
    [贪心经典算法]Kruskal算法
    [经典贪心算法]Prim算法
    Java容器之List接口
    Java容器之Set接口
    JDK中的泛型
    Java中ArrayList与数组间相互转换
    Java中的增强for循环
    Java容器之Iterator接口
    Java之容器
    eg_4
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/4743217.html
Copyright © 2011-2022 走看看