1. 程式人生 > >【BZOJ1176】Mokia(CDQ分治)

【BZOJ1176】Mokia(CDQ分治)

des NPU 解決 getc put ets 但是 拆分 etc

【BZOJ1176】Mokia(CDQ分治)

題面

BZOJ權限題啊,,,,
dbzoj真好

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範圍

題解

很明顯,只有時間靠前的修改的才會對時間靠後的修改產生影響。
同時,我們有三個維度:時間,\(x\)軸,\(y\)
因此,對於時間進行分治,按照\(x\)排序,
但是這樣子每次修改後,很不好解決詢問的問題。
我們把詢問拆開,拆分為\(4\)個詢問
啥?哪四個詢問,當然是二維前綴和的詢問啊。。。
然後就可以\(CDQ\)分治了。。

說起來,這看一眼就可以用樹套樹秒掉啊。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222222
#define lb(x) (x&(-x)) inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int S,n,tot,tim,cntq; int c[MAX],ans[MAX]; void add(int x,int w){while(x<=n)c[x]+=w,x+=lb(x);} int getsum(int x){int ret=0;while(x)ret+=c[x],x-=lb(x);return ret;} struct Opter{int t,x,y,w,ot,id;}q[MAX],tmp[MAX]; bool operator<(Opter a,Opter b) { if(a.x!=b.x)return a.x<b.x; if(a.y!=b.y)return a.y<b.y; return a.id<b.id; } void CDQ(int l,int r) { if(l==r)return; int mid=(l+r)>>1; for(int i=l;i<=r;++i) { if(q[i].t<=mid&&q[i].ot==1)add(q[i].y,q[i].w); if(q[i].t>mid&&q[i].ot==2)ans[q[i].id]+=q[i].w*getsum(q[i].y); } for(int i=l;i<=r;++i) if(q[i].t<=mid&&q[i].ot==1)add(q[i].y,-q[i].w); int t1=l-1,t2=mid; for(int i=l;i<=r;++i) if(q[i].t<=mid)tmp[++t1]=q[i]; else tmp[++t2]=q[i]; for(int i=l;i<=r;++i)q[i]=tmp[i]; CDQ(l,mid);CDQ(mid+1,r); } int main() { S=read();n=read(); while(233) { int opt=read(); if(opt==3)break; if(opt==1) { int x=read(),y=read(); q[++tot]=(Opter){++tim,x,y,read(),1}; } else { int x=read(),y=read(),X=read(),Y=read(); ans[++cntq]=(y-Y+1)*(X-x+1)*S;//++tim; q[++tot]=(Opter){++tim,x-1,y-1,+1,2,cntq}; q[++tot]=(Opter){++tim,X,Y,+1,2,cntq}; q[++tot]=(Opter){++tim,x-1,Y,-1,2,cntq}; q[++tot]=(Opter){++tim,X,y-1,-1,2,cntq}; } } sort(&q[1],&q[tot+1]); CDQ(1,tot); for(int i=1;i<=cntq;++i)printf("%d\n",ans[i]); return 0; }

【BZOJ1176】Mokia(CDQ分治)