[BZOJ1176]Mokia

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5
 
时隔五个月再做这道题又有新的理解
首先把操作看成四个二维前缀和相加减,然后对于每个操作有三个维度:时间,$x$轴,$y$轴
考虑对一个查询,哪些修改操作会对它产生影响,当且仅当在它之前发生且在它的左下方
所以我们可以按照$x$轴先排序消除$x$轴的影响
然后对归并排序时间戳使得左右两部分的操作有序
然后按时间戳加入修改和询问就完成了
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define M 2000010
 6 using namespace std;
 7 int read() {
 8     char ch=getchar();int x=0;
 9     while(ch>'9'||ch<'0') ch=getchar();
10     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
11     return x;
12 }
13 int n,S,tot,qcnt,tim;
14 int ans[M],f[M];
15 struct ASK{int t,x,y,w,ot,id;}q[M],tmp[M];
16 bool cmp(ASK a1,ASK a2) {
17     if(a1.x!=a2.x) return a1.x<a2.x;
18     if(a1.y!=a2.y) return a1.y<a2.y;
19     return a1.id<a2.id;
20 }
21 void add(int loc,int v) {
22     for(int i=loc;i<=n;i+=(i&-i)) f[i]+=v;
23 }
24 int query(int loc) {
25     int ans=0;
26     for(int i=loc;i;i-=(i&-i)) ans+=f[i];
27     return ans;
28 }
29 void CDQ(int l,int r) {
30     if(l==r) return;
31     int mid=(l+r)>>1;
32     CDQ(l,mid);CDQ(mid+1,r);
33     int t1=l,t2=mid+1,now=l;
34     while(t1<=mid||t2<=r) {
35         if(t1<=mid&&q[t1].t<q[t2].t||t2>r) {
36             if(q[t1].ot==1) add(q[t1].y,q[t1].w);
37             tmp[now++]=q[t1++];
38         }
39         else {
40             if(q[t2].ot==2) ans[q[t2].id]+=q[t2].w*query(q[t2].y);
41             tmp[now++]=q[t2++];
42         }
43     }
44     for(int i=l;i<=mid;i++) 
45         if(q[i].ot==1) 
46             add(q[i].y,-q[i].w);
47     for(int i=l;i<=r;i++) q[i]=tmp[i];
48 }
49 int main() {
50     S=read();n=read();
51     while(1) {
52         int opt=read();
53         if(opt==3) break;
54         if(opt==1) {
55             int x=read(),y=read(),z=read();
56             q[++tot]=(ASK){++tim,x,y,z,1};
57         }
58         else {
59             int x1=read(),y1=read(),x2=read(),y2=read();
60             ans[++qcnt]=(x2-x1+1)*(y2-y1+1)*S;
61             q[++tot]=(ASK){++tim,x1-1,y1-1,1,2,qcnt};
62             q[++tot]=(ASK){++tim,x2,y2,1,2,qcnt};
63             q[++tot]=(ASK){++tim,x1-1,y2,-1,2,qcnt};
64             q[++tot]=(ASK){++tim,x2,y1-1,-1,2,qcnt};
65         }
66     }
67     sort(q+1,q+1+tot,cmp);
68     CDQ(1,tot);
69     for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]);
70     return 0;
71 }

 

posted @ 2018-12-04 11:04  Slr  阅读(131)  评论(0编辑  收藏  举报