标签:cdq分治
题意:维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
这题在bz是贵族题= =,没有链接了
解法:cdq分治,第一维是时间t,第二维是x,第三维是y;每个操作看作一个三维序(t, x, y);假设修改操作是(t, x, y),两个查询操作分别是(t1, x1, y1) 和 (t1, x2, y2);实际上就要问,有多少个修改操作,满足t<=t1,x1<=x<=x2,y1<=y<=y2;这个用cdq分治就能做了,要将查询拆成四个点,利用容斥原理来做。不愿意细讲了= =,具体看代码吧
My code
//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#include<set>
#include<map>
using namespace std;
#define peter cout<<"i am peter"<<endl
#define fuck(x) cerr << #x << " <- " << x << endl
typedef long long ll;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
#define N 200010
int w,n,li[N],nli,ans[N];
struct Pair{
int ty, id;
int x, y, v;
Pair(){};
Pair(int ty1,int id1,int x1,int y1,int v1){
ty = ty1, id = id1,x = x1, y = y1, v = v1;
}
}p[N],s1[N],s2[N];
bool cmp1(const Pair a, const Pair b){
return a.x < b.x;
}
int sum[N];
void add(int x,int v){
for(int i = x; i <= nli; i += i&-i){
sum[i] += v;
}
}
int query(int x){
int ans = 0;
for(int i = x; i > 0; i -= i&-i){
ans += sum[i];
}
return ans;
}
void clear(int x){
for(int i = x; i <= nli; i += i&-i){
sum[i] = 0;
}
}
void cdq(int l,int r){
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid);
int n1 = 0, n2 = 0;
for(int i = l; i <= mid; i++) if(p[i].ty == 1) s1[++n1] = p[i];
for(int i = mid + 1; i <= r; i++) if(p[i].ty == 2) s2[++n2] = p[i];
sort(s1 + 1, s1 + 1 + n1, cmp1);
sort(s2 + 1, s2 + 1 + n2, cmp1);
int t1 = 1;
for(int t2 = 1; t2 <= n2; t2++){
for(;t1 <= n1 && s1[t1].x <= s2[t2].x; t1++){
add(s1[t1].y, s1[t1].v);
}
int id = s2[t2].id;
ans[id] += s2[t2].v * query(s2[t2].y);
}
for(int i = 1; i < t1; i++){
clear(s1[i].y);
}
cdq(mid + 1, r);
}
bool isq[N];
int nop;
int main(){
int t; t = read();
w = read();
for(int i = 1; ;i++){
t = read();
if(t == 3) break;
nop = nop + 1;
if(t == 1){
isq[i] = 0;
int x,y,v;
x = read(), y = read(), v = read();
p[++n] = Pair(t, i, x, y, v);
li[++nli] = y;
}
else if(t == 2){
isq[i] = 1;
int x1,y1,x2,y2;
x1 = read(), y1 = read(), x2 = read(), y2 = read();
p[++n] = Pair(t, i, x2, y2, +1);
p[++n] = Pair(t, i, x2, y1 - 1, -1);
p[++n] = Pair(t, i, x1 - 1, y2, -1);
p[++n] = Pair(t, i, x1 - 1, y1 - 1, +1);
li[++nli] = y2;
li[++nli] = y1 - 1;
}
}
sort(li + 1, li + 1 + nli);
nli = (int)(unique(li + 1, li + 1 + nli) - (li + 1));
for(int i = 1; i <= n; i++){
p[i].y = (int)(lower_bound(li + 1, li + 1 + nli, p[i].y) - li);
}
for(int i = 1; i <= nli; i++) sum[i] = 0;
for(int i = 1; i <= nop; i++) ans[i] = 0;
cdq(1, n);
for(int i = 1; i <= nop; i++){
if(isq[i]) printf("%d\n",ans[i]);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
BZOJ 1176 Mokia(cdq分治,解决一类在线查询问题)
标签:cdq分治
原文地址:http://blog.csdn.net/uestc_peterpan/article/details/47388689