BZOJ1176 [Balkan2007]Mokia 【CDQ分治】
2018-01-07 10:25
489 查看
题目
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
输入格式
第一行两个整数,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:表示输入结束
输出格式
对于每个输入2,输出一行,即输入2的答案
输入样例
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
输出样例
3
5
提示
保证答案不会超过int范围
题解
CDQ分治
每个询问分解成4个前缀和
然后每个询问或修改就有三维(x,y,t)
一个询问被一个修改影响当且仅当t1 > t2 且x1 >= x2 且 y1 >= y2
可以上CDQ分治
【可以顺便吧2683A了】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define lbt(x) (x & -x) using namespace std; const int maxn = 200005,maxm = 2000005,INF = 1000000000; inline int RD(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();} return out * flag; } LL S[maxm],N,s; void add(int u,int v){while (u <= N) S[u] += v,u += lbt(u);} LL sum(int u){LL ans = 0; while (u) ans += S[u],u -= lbt(u); return ans;} struct Que{LL x,y,id,v,pos,t;}Q[maxn],T[maxn]; inline bool operator <(const Que& a,const Que& b){ if (a.x == b.x && a.y == b.y) return a.t < b.t; if (a.x == b.x) return a.y < b.y; return a.x < b.x; } LL Qi = 0,ans[maxn]; void CDQ(int l,int r){ if (l == r) return; int mid = l + r >> 1,l1 = l,l2 = mid + 1; for (int i = l; i <= r; i++) if (Q[i].t <= mid && !Q[i].id) add(Q[i].y,Q[i].v); else if (Q[i].t > mid && Q[i].id) ans[Q[i].id] += Q[i].pos * sum(Q[i].y); for (int i = l; i <= r; i++){ //printf("[%lld,%lld],id = %lld,t = %lld\n",Q[i].x,Q[i].y,Q[i].id,Q[i].t); if (Q[i].t <= mid){ T[l1++] = Q[i]; if (!Q[i].id) add(Q[i].y,-Q[i].v); } else T[l2++] = Q[i]; } for (int i = l; i <= r; i++) Q[i] = T[i]; CDQ(l,mid); CDQ(mid + 1,r); } int main(){ //freopen("in.txt","r",stdin); //freopen("out1.txt","w",stdout); s = RD(); N = RD(); LL opt,a,b,c,d; while (true){ opt = RD(); if (opt == 3) break; if (opt & 1){ a = RD(),b = RD(),c = RD(); Q[++Qi] = (Que){a,b,0,c,0,Qi}; }else { a = RD(),b = RD(),c = RD(); d = RD(); int pos = ++ans[0]; Q[++Qi] = (Que){c,d,pos,0,1,Qi}; Q[++Qi] = (Que){c,b - 1,pos,0,-1,Qi}; Q[++Qi] = (Que){a - 1,d,pos,0,-1,Qi}; Q[++Qi] = (Que){a - 1,b - 1,pos,0,1,Qi}; ans[pos] = (c - a + 1) * (d - b + 1) * s; } } sort(Q + 1,Q + 1 + Qi); CDQ(1,Qi); REP(i,ans[0]) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- BZOJ 1176: [Balkan2007]Mokia | CDQ分治
- CDQ分治——BZOJ1176 [Balkan2007]Mokia
- BZOJ 1176: [Balkan2007]Mokia (CDQ分治)
- bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组
- bzoj 1176 [Balkan2007]Mokia 【CDQ分治】
- BZOJ 1176([Balkan2007]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分治]
- bzoj 1176: [Balkan2007]Mokia&&2683: 简单题 -- cdq分治
- BZOJ 1176: [Balkan2007]Mokia&&2683: 简单题|cdq分治
- BZOJ 1176: [Balkan2007]Mokia( CDQ分治 + 树状数组 )
- [BZOJ1176][[Balkan2007]Mokia][CDQ分治]
- cdq分治入门--BZOJ1176: [Balkan2007]Mokia
- BZOJ 1176 [Balkan2007]Mokia ——CDQ分治
- BZOJ1176 [Balkan2007]Mokia 【CDQ分治】
- BZOJ 1176 [Balkan2007]Mokia [CDQ分治+树状数组]