题目大意:
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.
思路:
把每个询问拆成四个点
然后按时间cdq分治
查询以每个点为右上角的矩形内 最大权值和
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 2001000 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int m,s,c[MAXN],n,ans[MAXN],cnt,vis[MAXN]; 21 struct data {int x,y,pos,val,Pos;}g[MAXN]; 22 bool cmp(data a,data b) {return a.x<b.x||(a.x==b.x&&a.y<b.y)||(a.x==b.x&&b.y==a.y&&a.val>b.val);} 23 int lowbit(int x) {return x&(-x);} 24 void add(int x,int t) {for(int i=x;i<=m;i+=lowbit(i)) c[i]+=t;} 25 int query(int x) {int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;} 26 void cdq(int l,int r) 27 { 28 if(l==r) return; 29 int mid=(l+r)>>1; 30 data m=g[mid]; 31 cdq(l,mid);cdq(mid+1,r); 32 sort(g+l,g+r+1,cmp); 33 for(int i=l;i<=r;i++) 34 { 35 if(g[i].Pos<=m.Pos&&g[i].val>0) add(g[i].y,g[i].val); 36 else if(g[i].Pos>m.Pos&&g[i].val<0) ans[g[i].pos]+= (g[i].val+2)*query(g[i].y); 37 } 38 for(int i=l;i<=r;i++) if(g[i].Pos<=m.Pos&&g[i].val>0) add(g[i].y,-g[i].val); 39 } 40 int main() 41 { 42 s=read(),m=read();int a; 43 while(a=read()) 44 { 45 if(a==3) break; 46 if(a&1) g[++n].x=read(),g[n].y=read(),g[n].val=read(),g[n].pos=0,g[n].Pos=n; 47 else 48 { 49 g[++n].x=read()-1,g[n].y=read()-1,g[n].val=-1,g[n].pos=++cnt,g[n].Pos=n; 50 g[++n].x=read(),g[n].y=read(),g[n].val=-1,g[n].pos=cnt,g[n].Pos=n,n++; 51 g[n].x=g[n-2].x,g[n].y=g[n-1].y,g[n].val=-3,g[n].pos=cnt,g[n].Pos=n,n++; 52 g[n].x=g[n-2].x,g[n].y=g[n-3].y,g[n].val=-3,g[n].pos=cnt,g[n].Pos=n; 53 } 54 } 55 cdq(1,n); 56 for(int i=1;i<=cnt;i++) printf("%d ",ans[i]); 57 }
(因为树状数组开小了调了很多天
upd:
事实证明归并快很多
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 2001000 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int m,s,c[MAXN],n,ans[MAXN],cnt,vis[MAXN]; 21 struct data 22 { 23 int x,y,pos,val,Pos; 24 bool operator < (const data &b) const 25 { 26 return x<b.x||(x==b.x&&y<b.y)||(x==b.x&&b.y==y&&val>b.val); 27 } 28 bool operator == (const data &b) const 29 { 30 return x==b.x&&b.y==y&&val==b.val; 31 } 32 }g[MAXN],tmp[MAXN]; 33 int lowbit(int x) {return x&(-x);} 34 void add(int x,int t) {for(int i=x;i<=m;i+=lowbit(i)) c[i]+=t;} 35 int query(int x) {int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;} 36 void cdq(int l,int r) 37 { 38 if(l==r) return; 39 int mid=(l+r)>>1; 40 data m=g[mid];int tot=l-1,i=l,j=mid+1; 41 cdq(l,mid);cdq(mid+1,r); 42 for(;tot<r;) 43 { 44 if((g[i]<g[j]||j>r)&&i<=mid) tmp[++tot]=g[i++]; 45 else if((g[j]<g[i]||g[j]==g[i]||i>mid)&&j<=r) tmp[++tot]=g[j++]; 46 if(tmp[tot].Pos<=m.Pos&&tmp[tot].val>0) add(tmp[tot].y,tmp[tot].val); 47 else if(tmp[tot].Pos>m.Pos&&tmp[tot].val<0) ans[tmp[tot].pos]+= (tmp[tot].val+2)*query(tmp[tot].y); 48 } 49 for(int i=l;i<=r;i++) g[i]=tmp[i]; 50 for(int i=l;i<=r;i++) if(g[i].Pos<=m.Pos&&g[i].val>0) add(g[i].y,-g[i].val); 51 } 52 int main() 53 { 54 s=read(),m=read();int a; 55 while(a=read()) 56 { 57 if(a==3) break; 58 if(a&1) g[++n].x=read(),g[n].y=read(),g[n].val=read(),g[n].pos=0,g[n].Pos=n; 59 else 60 { 61 g[++n].x=read()-1,g[n].y=read()-1,g[n].val=-1,g[n].pos=++cnt,g[n].Pos=n; 62 g[++n].x=read(),g[n].y=read(),g[n].val=-1,g[n].pos=cnt,g[n].Pos=n,n++; 63 g[n].x=g[n-2].x,g[n].y=g[n-1].y,g[n].val=-3,g[n].pos=cnt,g[n].Pos=n,n++; 64 g[n].x=g[n-2].x,g[n].y=g[n-3].y,g[n].val=-3,g[n].pos=cnt,g[n].Pos=n; 65 } 66 } 67 cdq(1,n); 68 for(int i=1;i<=cnt;i++) printf("%d ",ans[i]); 69 }