cdq分治入门--BZOJ1176: [Balkan2007]Mokia

对w*w,w<=2000000的矩形,一开始全是0(或一开始全是s),n<=170000个操作,每次操作:矩阵内某点加上一个数,查某一个子矩阵的和,保证修改数<=160000,询问数<=10000。

这还是一个比较明显的三维偏序:时间维,以及x和y。由于现在时间维是一个Ti<Tj,而x和y是要查x1<=x<=x2,y1<=y<=y2,查一个范围答案在归并排序直接查不方便,所以一个询问拆4个,就变成普通的三维偏序了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<algorithm>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,m,s;
 9 #define maxn 300011
10 #define maxm 2000011
11 struct Point
12 {
13     int x,y,v;bool type;
14     //type=1:Q type=0:A 
15 }a[maxn];
16 int ans[maxn];
17 
18 struct BIT
19 {
20     int a[maxm],n;
21     void clear(int m) {n=m;memset(a,0,sizeof(a));}
22     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
23     int query(int x) {int ans=0;for (;x;x-=x&-x) ans+=a[x];return ans;}
24 }t;
25 
26 int ord[maxn],tmpord[maxn];
27 void solve(int L,int R)
28 {
29     if (L==R) {ord[L]=L;return;}
30     const int mid=(L+R)>>1;
31     solve(L,mid);
32     solve(mid+1,R);
33     int i=L,j=mid+1,k=L;
34     while (i<=mid && j<=R)
35     {
36         if (a[ord[i]].x<=a[ord[j]].x)
37         {
38             if (a[ord[i]].type==0)
39                 t.add(a[ord[i]].y,a[ord[i]].v);
40             tmpord[k++]=ord[i++];
41         }
42         else
43         {
44             if (a[ord[j]].type)
45                 ans[ord[j]]+=t.query(a[ord[j]].y);
46             tmpord[k++]=ord[j++];
47         }
48     }
49     for (;j<=R;j++)
50     {
51         if (a[ord[j]].type) ans[ord[j]]+=t.query(a[ord[j]].y);
52         tmpord[k++]=ord[j];
53     }
54     for (int ii=L;ii<i;ii++) if (!a[ord[ii]].type) t.add(a[ord[ii]].y,-a[ord[ii]].v);
55     for (;i<=mid;i++) tmpord[k++]=ord[i];
56     for (int x=L;x<=R;x++) ord[x]=tmpord[x];
57 }
58 
59 int main()
60 {
61     scanf("%d%d",&s,&m);
62     t.clear(m);
63     n=0;
64     int op,x,y,z,w;
65     while (scanf("%d",&op) && op!=3)
66     {
67         if (op-1)
68         {
69             scanf("%d%d%d%d",&x,&y,&z,&w);
70             a[++n]=(Point){x-1,y-1,1,1};
71             a[++n]=(Point){x-1,w,-1,1};
72             a[++n]=(Point){z,y-1,-1,1};
73             a[++n]=(Point){z,w,1,1};
74         }
75         else
76         {
77             scanf("%d%d%d",&x,&y,&z);
78             a[++n]=(Point){x,y,z,0};
79         }
80     }
81     solve(1,n);
82     
83     for (int i=1;i<=n;i++) if (a[i].type)
84     {
85         int Ans=0;
86         for (int to=i+4;i<to;i++) Ans+=ans[i]*a[i].v;
87         i--;
88         printf("%d
",Ans);
89     }
90     return 0;
91 }
View Code

这题面的s没有用,怎么题面也不改。。

原文地址:https://www.cnblogs.com/Blue233333/p/7890221.html