1. 程式人生 > >[BZOJ1176][Balkan2007]Mokia cdq+樹狀數組

[BZOJ1176][Balkan2007]Mokia cdq+樹狀數組

scanf input 技術分享 增加 hide ble lowbit ring stream

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

[BZOJ1176][Balkan2007]Mokia cdq+樹狀數組