BZOJ--1176(CDQ分治)
2015-08-09 18:57:08
【传送门】CDQ第一道启蒙题~
题意:最多16万个修改,1万个询问,维护的是一个W*W的矩阵(W<=2000000),每个修改是给一个格子加权值,每个询问是询问一个子矩阵内的权值和。
思路:考虑CDQ分治,首先将子矩阵查问拆分为4个查询,然后容斥搞一下,将所有询问按照 x 轴排序,然后将所有操作按照时间一分为二。
(1)先处理掉前半边区间的修改对后半边询问造成的影响,由于已经按照 x 轴排序了,所以用一颗树状数组就可以维护点权和。
(2)然后还原前半边区间的影响。
(3)将前半边操作放在左边,后半边操作放在右边,然后分治处理两边。
#include <cstdio> #include <ctime> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB push_back typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 2000010; int s,w,m; int c[2000010]; int ans[200010]; inline int lowbit(int x){ return x & (-x); } void Update(int x,int d){ while(x <= w){ c[x] += d; x += lowbit(x); } } int Getsum(int x){ int res = 0; while(x){ res += c[x]; x -= lowbit(x); } return res; } struct node{ int x,y,id,typ,val,f,pos; bool operator < (const node &b) const{ if(x == b.x && y == b.y) return typ < b.typ; if(x == b.x) return y < b.y; return x < b.x; } }Q[200010],tmp[200010]; void CDQ(int l,int r){ if(l == r) return; int mid = getmid(l,r); CDQ(l,mid); CDQ(mid + 1,r); sort(Q + l,Q + r + 1); //l -> mid , mid + 1 -> r for(int i = l; i <= r; ++i){ if(Q[i].id <= mid && Q[i].typ == 0) Update(Q[i].y,Q[i].val); if(Q[i].id > mid && Q[i].typ == 1) ans[Q[i].pos] += Q[i].f * Getsum(Q[i].y); } for(int i = l; i <= r; ++i) if(Q[i].id <= mid && Q[i].typ == 0) Update(Q[i].y,-Q[i].val); } int main(){ int f,X1,Y1,X2,Y2; scanf("%d%d",&s,&w); m = 0; int ans_cnt = 0; while(1){ scanf("%d",&f); if(f == 3) break; if(f == 1){ ++m; scanf("%d%d%d",&Q[m].x,&Q[m].y,&Q[m].val); Q[m].id = m; Q[m].typ = 0; //修改 } else{ scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2); ans_cnt++; Q[++m].x = X2; Q[m].y = Y2; Q[m].id = m; Q[m].typ = 1; Q[m].f = 1; Q[m].pos = ans_cnt; Q[++m].x = X1 - 1; Q[m].y = Y1 - 1; Q[m].id = m; Q[m].typ = 1; Q[m].f = 1; Q[m].pos = ans_cnt; Q[++m].x = X2; Q[m].y = Y1 - 1; Q[m].id = m; Q[m].typ = 1; Q[m].f = -1; Q[m].pos = ans_cnt; Q[++m].x = X1 - 1; Q[m].y = Y2; Q[m].id = m; Q[m].typ = 1; Q[m].f = -1; Q[m].pos = ans_cnt; } } CDQ(1,m); for(int i = 1; i <= ans_cnt; ++i){ printf("%d\n",ans[i]); } return 0; }