suoi44 核能显示屏 (cdq分治)

首先二维树状数组肯定开不下

仿照二维树状数组的做法,如果有差分数组$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$,那么就有:

$$sum[x][y]=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{sumlimits_{k=1}^{i}{sumlimits_{l=1}^{j}{d[k][l]}}}}$$

$$=sumlimits_{i=1}^{x}{sumlimits_{k=1}^{i}{sumlimits_{j=1}^{y}{((y+1)d[k][j]-j*d[k][j])}}}$$

$$=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{(x+1)(y+1)d[i][j]-(x+1)*j*d[i][j]-(y+1)*i*d[i][j]+i*j*d[i][j]}}$$

所以把询问拆成四个(前缀和)、修改拆成四个(差分))

已经按时间排好序,然后把x作为第二维来cdq,开d,i*d,j*d,i*j*d四个树状数组统计答案就可以了

上帝造题的七分钟也可以这样做,不过常数太大要吸氧

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e4+10,maxm=3e4+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 struct Node{
16     int t,x,y,o;ll v;
17     Node(int a=0,int b=0,int c=0,int d=0,int e=0){
18         t=a,x=b,y=c,v=d,o=e;
19     }//o==1查 o==0改
20 }op[maxm*4],tmp[maxm*4];
21 ll dd[maxn],id[maxn],jd[maxn],ijd[maxn];
22 ll ans[maxm];
23 int N,M;
24 bool isask[maxm];
25 
26 inline int lowbit(int x){return x&(-x);}
27 inline void add(ll *t,int x,ll y){
28     for(;x<=N;x+=lowbit(x)) t[x]+=y;
29 }
30 inline ll query(ll *t,int x){
31     ll re=0;for(;x;x-=lowbit(x)) re+=t[x];return re;
32 }
33 
34 void cdq(int l,int r){
35     if(l==r) return;
36     int m=l+r>>1;
37     cdq(l,m);cdq(m+1,r);
38     int p=l,q=m+1,n=0;
39     for(;q<=r;q++){
40         for(;p<=m&&op[p].x<=op[q].x;p++){
41             tmp[++n]=op[p];
42             if(op[p].o!=0) continue;
43             add(dd,op[p].y,op[p].v);
44             add(id,op[p].y,op[p].v*op[p].x);
45             add(jd,op[p].y,op[p].v*op[p].y);
46             add(ijd,op[p].y,op[p].v*op[p].x*op[p].y);
47         }
48         tmp[++n]=op[q];
49         if(op[q].o!=1) continue;
50         ll re=query(dd,op[q].y)*(op[q].x+1)*(op[q].y+1);
51         re-=query(id,op[q].y)*(op[q].y+1);
52         re-=query(jd,op[q].y)*(op[q].x+1);
53         re+=query(ijd,op[q].y);
54         ans[op[q].t]+=re*op[q].v;
55     }for(;p<=m;p++) tmp[++n]=op[p];
56     for(int p=l;p<=m&&op[p].x<=op[r].x;p++){
57         if(op[p].o!=0) continue;
58         add(dd,op[p].y,-op[p].v);
59         add(id,op[p].y,-op[p].v*op[p].x);
60         add(jd,op[p].y,-op[p].v*op[p].y);
61         add(ijd,op[p].y,-op[p].v*op[p].x*op[p].y);
62     }
63     memcpy(op+l,tmp+1,sizeof(Node)*n);
64 }
65 
66 int main(){
67     //freopen("","r",stdin);
68     int i,j;
69     N=rd(),M=rd();
70     for(i=1,j=0;i<=M;i++){
71         int a=rd(),x1=rd(),y1=rd(),x2=rd(),y2=rd();
72         if(!a){
73             op[++j]=Node(i,x2,y2,1,1);
74             if(x1>1&&y1>1) op[++j]=Node(i,x1-1,y1-1,1,1);
75             if(x1>1) op[++j]=Node(i,x1-1,y2,-1,1);
76             if(y1>1) op[++j]=Node(i,x2,y1-1,-1,1);
77             isask[i]=1;
78         }else{
79             op[++j]=Node(i,x1,y1,a,0);
80             if(x2<N&&y2<N) op[++j]=Node(i,x2+1,y2+1,a,0);
81             if(y2<N) op[++j]=Node(i,x1,y2+1,-a,0);
82             if(x2<N) op[++j]=Node(i,x2+1,y1,-a,0);
83         }
84     }
85     cdq(1,j);
86     for(i=1;i<=M;i++){
87         if(isask[i]) printf("%lld
",ans[i]); 
88     }
89     return 0;
90 }
原文地址:https://www.cnblogs.com/Ressed/p/9777876.html