BZOJ-10-1176: [Balkan2007]Mokia-CDQ第二类应用

思路 :按照操作的时间进行分治,这样转化成了 时间t ,x坐标,y坐标 经典的三维偏序。

最初时间就是递增顺序,无需排序直接进行第二维的分治,类似归并排序处理x坐标,在保证

x有序的情况下进行更新y坐标的树状数组。求一个  (x1,y1)   - (x2,y2)矩形内点的个数,简单容斥一下

求[ (1,1) ——(x1-1,y1-1) ]+[ (1,1) ——(x2,y2) ]-[ (1,1) ——(x1-1,y1) ]-[ (1,1) ——(x1,y1-1) ]   

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 2234567
ll op,w,s,x[3],y[3];
ll cnt,q[maxn],tot;
ll ans[maxn],tree[maxn];
struct node
{
    int x,y,id,ad;
} data[maxn],cp[maxn];
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int d)
{
    while(x<=w)
    {
        tree[x]+=d;
        x+=lowbit(x);
    }
}
ll query(int x)
{
    ll re=0;
    while(x>0)
    {
        re+=tree[x];
        x-=lowbit(x);
    }
    return re;
}
void cdq(int l,int r)
{
    if(l>=r)return ;
    int mid=(l+r)/2;
    cdq(l,mid);
    cdq(mid+1,r);
    int t1=l,t2=mid+1,ct=l;
    while(t2<=r)
    {
        while(data[t1].x<=data[t2].x&&t1<=mid)
        {
            if(data[t1].id==0)
                add(data[t1].y,data[t1].ad);
            cp[ct++]=data[t1++];
        }
        if(data[t2].id!=0)ans[data[t2].ad]+=query(data[t2].y);
        cp[ct++]=data[t2++];
    }
    for(int i=l; i<t1; i++)
        if(data[i].id==0)
            add(data[i].y,-data[i].ad);
    while(t1<=mid)cp[ct++]=data[t1++];
    while(t2<=r)cp[ct++]=data[t2++];
    for(int i=l; i<=r; i++)
        data[i]=cp[i];
}
int main()
{
    scanf("%lld%lld",&s,&w);
    while(1)
    {
        scanf("%lld",&op);
        if(op==1)
        {
            data[++cnt].id=0;
            scanf("%lld%lld%lld",&data[cnt].x,&data[cnt].y,&data[cnt].ad);
        }
        else if(op==2)
        {
            scanf("%lld%lld%lld%lld",&x[1],&y[1],&x[2],&y[2]);
            q[++tot]=cnt+1;
            ans[cnt+4]+=(y[2]-y[1]+1)*(x[2]-x[1]+1)*s;
            data[++cnt].x=x[1]-1,data[cnt].y=y[1]-1,data[cnt].id=2,data[cnt].ad=cnt;
            data[++cnt].x=x[1]-1,data[cnt].y=y[2],data[cnt].id=2,data[cnt].ad=cnt;
            data[++cnt].x=x[2],data[cnt].y=y[1]-1,data[cnt].id=2,data[cnt].ad=cnt;
            data[++cnt].x=x[2],data[cnt].y=y[2],data[cnt].id=3,data[cnt].ad=cnt;
        }
        else break;
    }
    cdq(1,cnt);
    for(int i=1; i<=tot; i++)
        printf("%lld
",ans[q[i]+3]-ans[q[i]+1]-ans[q[i]+2]+ans[q[i]]);
    return 0;
}

  

原文地址:https://www.cnblogs.com/SDUTNING/p/10280387.html