bzoj 1176: Mokia CDQ分治
2017-02-15 20:28
288 查看
人生第一道自己写的CDQ LOL~~~
题目大意
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
题解
CDQ分治裸上啊...
啥是CDQ啊?....
怎么说呢..
CDQ分治是一种思想.
将整个序列分成两半递归处理,但是由于左边对右边的序列存在着不可忽略的影响,所以需要在递归时考虑左半边序列对右半边序列的影响。
即CDQ的核心思想.(大概...)
至于具体的实现过程,这种东西还是对着代码比较好学。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; inline void read(int &x){ x=0;char ch;bool flag = false; while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true; while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x; } const int maxm = 210010; const int maxn = 2100000; struct Node{ int op,x,y; int val,id; bool friend operator < (const Node &a,const Node &b){ return a.x < b.x; }Node(){} Node(int a,int b,int c,int d,int e){op=a;x=b;y=c;val=d;id = e;} }a[maxm],atmp[maxm]; int cnt,n; int anss[10010]; int c[maxn],tmp[maxm]; #define lowbit(x) (x&-x) inline void modify(int x,int y){ if(!x) return; for(;x <= n;x+=lowbit(x)) c[x] += y; } inline int query(int x){ int ret = 0; for(;x>=1;x-=lowbit(x)) ret += c[x]; return ret; } inline void merge(int l,int r){ if(l == r) return; int mid = l+r >> 1; int i = l,j = mid+1,k = l; while(i <= mid || j <= r){ if(j > r || ( i <= mid && a[i].x < a[j].x)) atmp[k++] = a[i++]; else atmp[k++] = a[j++]; }for(int i=l;i<=r;++i) a[i] = atmp[i]; } void solve(int l,int r){//CDQ的分治 if(l == r) return ; int mid = l+r >> 1; solve(l,mid);//递归处理子序列 solve(mid+1,r); merge(l,mid);//对左右序列分别排序 merge(mid+1,r); //下面开始考虑左序列(中的插入操作)对右序列(中的询问操作)的影响 int p = l,cnt = 0; for(int i = mid+1;i<=r;++i){ if(a[i].op == 2){//如果这是个询问操作 while(p <= mid && a[p].x <= a[i].x){ if(a[p].op == 1){//对于左序列所有的操作,更新影响 tmp[++cnt] = p; modify(a[p].y,a[p].val); }++p; }anss[a[i].id] += a[i].val*query(a[i].y);//做出贡献 } } //清空树状数组,注意不能memset for(int i=1;i<=cnt;++i) modify(a[tmp[i]].y,-a[tmp[i]].val); } int main(){ read(cnt);read(n); int op,x1,y1,x2,y2,x; int query_id = 0; while(1){ read(op);if(op == 3) break; if(op == 1){ read(x1);read(y1);read(x); a[++cnt] = (Node){op,x1,y1,x,0}; }else{ x = ++query_id; read(x1);read(y1);read(x2);read(y2); //将所有的询问做成前缀和差分的形式 a[++cnt] = (Node){op,x2,y2,1,x}; a[++cnt] = (Node){op,x1-1,y2,-1,x}; a[++cnt] = (Node){op,x2,y1-1,-1,x}; a[++cnt] = (Node){op,x1-1,y1-1,1,x}; } } solve(1,cnt); for(int i=1;i<=query_id;++i){ printf("%d\n",anss[i]); } getchar();getchar(); return 0; }
相关文章推荐
- BZOJ1176 [Balkan2007]Mokia 【CDQ分治】
- bzoj1176: [Balkan2007]Mokia【cdq分治】
- BZOJ1176 [Balkan2007]Mokia 【CDQ分治】
- 【BZOJ1176】Mokia(CDQ分治)
- BZOJ 1176: [Balkan2007]Mokia&&2683: 简单题|cdq分治
- [BZOJ1176]-Mokia-CDQ分治
- cdq分治入门--BZOJ1176: [Balkan2007]Mokia
- 【bzoj 1176】Mokia(CDQ分治)
- bzoj 1176 Mokia(CDQ分治,BIT)
- BZOJ 1176 [Balkan2007]Mokia ——CDQ分治
- BZOJ 1176 [Balkan2007]Mokia [CDQ分治+树状数组]
- CDQ分治——BZOJ1176 [Balkan2007]Mokia
- BZOJ 1176 Mokia(CDQ分治)
- 【bzoj】【1176】【mokia】【cdq分治】
- BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)
- 【BZOJ】1176: [Balkan2007]Mokia(cdq分治)
- BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)
- BZOJ 1176: [Balkan2007]Mokia [CDQ分治]
- [BZOJ1176][[Balkan2007]Mokia][CDQ分治]
- bzoj 1176: [Balkan2007]Mokia 【CDQ分治】