久仰cdq(分治)大名,今日才来造访,礼数不周也。。。。。(发个牢骚~)
所谓cdq分治,就是分治所有操作,计算[l,mid]中的修改对[mid+1,r]中的询问的影响。
无法理解的同学可以借助归并排序的思想思考。
抄袭别人讲以上的话吧
1、T(n)=2T(n/2)+O(kn)的解是T(n)=O(kn log n)
2、T(n)=2T(n/2)+O(kn log n)的解是T(n)=O(kn log^2 n)
3、T(n)=2T(n/2)+O(k)的解是T(n)=O(kn)
所以cdq分治的复杂度也可以简单的算出来了。
cdq能处理的题目必须满足:1、允许离线 2、前面的修改对后面的影响很容易算出来
比如说这一题
在[l,mid]部分的修改按x排序从小到大加进一个树状数组里,不断更新对[mid+1,r]的影响。
复杂度就是第二种计算方式,可就是O(q log^2 w)
猥琐的code如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
const int Maxn=200000;
int x1[Maxn],x2[Maxn],y1[Maxn],y2[Maxn],tr[Maxn];
int a[Maxn],b[Maxn],c[Maxn],k[Maxn],ans[Maxn];
int n,m,s,w,i;
struct arr{
int x,l,r,k,c;
bool operator <(const arr &a)const
{ return x<a.x; }
} qk[Maxn];
struct ad{
int x,y,w;
bool operator <(const ad &a)const
{ return x<a.x; }
} g[Maxn];
int query(int x){
int ret=0;
for (int i=x;i>0;i-=lowbit(i))
ret+=tr[i];
return ret;
}
void ins(int x,int s){
for (int i=x;i<=m;i+=lowbit(i))
tr[i]+=s;
}
void merge(int l,int r){
if (l==r) return;
int mid=(l+r)>>1, t=0, tt=0, i, j;
merge(l,mid);
for (i=mid+1;i<=r;i++)
if (k[i]==2){
qk[++t]=(arr){x1[i]-1, y1[i], y2[i], i, 0};
qk[++t]=(arr){x2[i], y1[i], y2[i], i, 1};
}
sort(qk+1,qk+t+1);
for (i=l;i<=mid;i++)
if (k[i]==1) g[++tt]=(ad){x1[i],y1[i],x2[i]};
sort(g+1,g+tt+1);
for (i=1,j=1;i<=tt;i++){
while (j<=t && qk[j].x<g[i].x){
if (qk[j].c==0)
ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-1);
else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-1);
j++;
}
ins(g[i].y,g[i].w);
}
while (j<=t){
if (qk[j].c==0)
ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-1);
else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-1);
j++;
}
for (i=1;i<=tt;i++)
ins(g[i].y,-g[i].w);
merge(mid+1,r);
}
int main(){
//freopen("1176.in","r",stdin);
//freopen("1176.out","w",stdout);
scanf("%d%d",&s,&w);
n=1;
while (true){
scanf("%d",&k[n]);
if (k[n]==0 || k[n]==3) break;
if (k[n]==1){
scanf("%d%d%d",&x1[n],&y1[n],&x2[n]);
c[++m]=y1[n];
}else
if (k[n]==2){
scanf("%d%d%d%d",&x1[n],&y1[n],&x2[n],&y2[n]);
ans[n]+=s*(x2[n]-x1[n]+1)*(y2[n]-y1[n]+1);
c[++m]=y1[n]; c[++m]=y2[n];
}
n++;
}
sort(c+1,c+m+1);
m=unique(c+1,c+m+1)-c-1;
for (i=1;i<n;i++){
y1[i]=lower_bound(c+1,c+m+1,y1[i])-c;
if (k[i]==2)
y2[i]=lower_bound(c+1,c+m+1,y2[i])-c;
}
merge(1,--n);
for (i=1;i<=n;i++)
if (k[i]==2) printf("%d\n",ans[i]);
return 0;
}
cdq分治的精华远不止如此,今后慢慢研习