[BZOJ1176][Balkan2007]Mokia cdq+树状数组

1176: [Balkan2007]Mokia

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 3134  Solved: 1395
[Submit][Status][Discuss]

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

HINT

 

保证答案不会超过int范围

 

Source

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxq 800000
 8 #define ll long long
 9 using namespace std;
10 struct data {ll id,x,y,tp,f,a,p;}t[maxq],tmp[maxq];
11 ll s,w;
12 ll ans[maxq];
13 int cnt;
14 bool cmp1(data t1,data t2) {return t1.x==t2.x?t1.id<t2.id:t1.x<t2.x;}
15 int ask;
16 ll sum[4000000];
17 int lowbit(int x) {return x&(-x);}
18 bool vis[maxq];
19 void insert(int x,ll ad) {for(int i=x;i<=w;i+=lowbit(i)) sum[i]+=ad;}
20 ll query(int x) {
21     ll re=0;
22     for(int i=x;i;i-=lowbit(i)) re+=sum[i];
23     return re;
24 }
25 void cdq(int l,int r) {
26     if(l==r) return;
27     int mid=l+r>>1;
28     int lp=l,rp=mid+1;
29     for(int i=l;i<=r;i++) {
30         if(t[i].tp==2) {
31             if(t[i].id>mid){ans[t[i].p]+=t[i].f*query(t[i].y);vis[t[i].p]=1;}
32          }
33         else {if(t[i].id<=mid) insert(t[i].y,t[i].a);}
34     }
35     for(int i=l;i<=r;i++) if(t[i].tp==1&&t[i].id<=mid) insert(t[i].y,-t[i].a);
36     for(int i=l;i<=r;i++) {
37         if(t[i].id<=mid) tmp[lp++]=t[i];
38         else tmp[rp++]=t[i];
39     }
40     for(int i=l;i<=r;i++) t[i]=tmp[i];
41     cdq(l,mid);cdq(mid+1,r);
42 }
43 void add(ll x1,ll y1,ll id,ll tp,ll f) {t[cnt].p=id;t[cnt].f=f;t[cnt].tp=tp;t[cnt].x=x1;t[cnt].y=y1;t[cnt].id=cnt;}
44 int main() {
45     scanf("%lld%lld",&s,&w);
46     int tp;
47     while(scanf("%d",&tp)) {
48         ask++;
49         if(tp==3) break;
50         if(tp==1) {cnt++;scanf("%lld%lld%lld",&t[cnt].x,&t[cnt].y,&t[cnt].a);t[cnt].id=cnt;t[cnt].tp=1;}
51         else {
52             ll x1,y1,x2,y2;
53             scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
54             cnt++;add(x1-1,y1-1,ask,2,1);cnt++;add(x2,y2,ask,2,1);
55             cnt++;add(x1-1,y2,ask,2,-1);cnt++;add(x2,y1-1,ask,2,-1);
56             ans[ask]+=(y2-y1+1)*(x2-x1+1)*s;
57         }
58     }
59     sort(t+1,t+cnt+1,cmp1);
60     cdq(1,cnt);
61     for(int i=1;i<=ask;i++) if(vis[i]) printf("%lld\n",ans[i]);
62 }
View Code

 

posted @ 2018-03-21 19:53  wls001  阅读(170)  评论(0编辑  收藏  举报