BZOJ 1176 [Balkan2007]Mokia ——CDQ分治
【题目分析】
同BZOJ2683,只需要提前处理s对结果的影响即可。
CDQ的思路还是很清晰的。
排序解决一维,
分治时间,
树状数组解决一维。
复杂度是两个log
【代码】
#include <cstdio> #include <cstring> #include <cstdlib> //#include <cmath> #include <set> #include <map> #include <string> #include <algorithm> #include <vector> #include <iostream> #include <queue> using namespace std; #define maxn 2000005 int read() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } struct data{ int opt,id; int x,y,f,t; }q[maxn],eq[maxn]; int ans[maxn],s; int n,tot=0,cnt=0,opt,x1,y1,x2,y2,a; struct Bit{ int a[maxn]; void init(){memset(a,0,sizeof a);} void add(int x,int f) {for (;x<=n;x+=x&(-x)) a[x]+=f;} int sum(int x) { int ret=0; for (;x;x-=x&(-x)) ret+=a[x]; return ret; } }t; bool cmp(data a,data b) { if (a.x==b.x&&a.y==b.y) return a.opt<b.opt; if (a.x==b.x) return a.y<b.y; return a.x<b.x; } void solve(int l,int r) { if (l==r) return ; int mid=(l+r)/2; for (int i=l;i<=r;++i) { if (q[i].t<=mid&&q[i].opt==1) t.add(q[i].y,q[i].f); if ( q[i].t>mid&&q[i].opt==2) ans[q[i].id]+=t.sum(q[i].y)*q[i].f; } for (int i=l;i<=r;++i) if (q[i].t<=mid&&q[i].opt==1) t.add(q[i].y,-q[i].f); int l1=l,l2=mid+1; for (int i=l;i<=r;++i) {if (q[i].t<=mid) eq[l1++]=q[i]; else eq[l2++]=q[i];} for (int i=l;i<=r;++i) q[i]=eq[i]; solve(l,mid); solve(mid+1,r); } int main() { s=read();n=read(); while (scanf("%d",&opt)!=EOF&&opt!=3) { if (opt==1) { q[++cnt].opt=opt; q[cnt].x=read(); q[cnt].y=read(); q[cnt].f=read(); q[cnt].t=cnt; } else { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); ++tot; ans[tot]+=(x2-x1+1)*(y2-y1+1)*s; q[++cnt].opt=opt; q[cnt].x=x1-1; q[cnt].y=y1-1; q[cnt].f=1; q[cnt].t=cnt; q[cnt].id=tot; q[++cnt].opt=opt; q[cnt].x=x1-1; q[cnt].y=y2; q[cnt].f=-1; q[cnt].t=cnt; q[cnt].id=tot; q[++cnt].opt=opt; q[cnt].x=x2; q[cnt].y=y1-1; q[cnt].f=-1; q[cnt].t=cnt; q[cnt].id=tot; q[++cnt].opt=opt; q[cnt].x=x2; q[cnt].y=y2; q[cnt].f=1; q[cnt].t=cnt; q[cnt].id=tot; } } sort(q+1,q+cnt+1,cmp); solve(1,cnt); for (int i=1;i<=tot;++i) printf("%d\n",ans[i]); }