陈丹琪分治

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

原文地址:https://www.cnblogs.com/gaolzzxin/p/4743217.html