ACdream 1157 Segments(CDQ分治)

来源:互联网 发布:300英雄各级宝石数据 编辑:程序博客网 时间:2024/06/09 03:12

Description
由3种类型操作:
1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]
2)C i (1-base) 删除第i条增加的线段,保证每条插入线段最多插入一次,且这次删除操作一定合法
3) Q L R(1 <= L <= R <= 1000000000) 查询目前存在的线段中有多少条线段完全包含[L,R]这个线段,线段X被线段Y完全包含即LY <= LX
<= RX <= RY)
Input
多组数据,每组数据N
接下来N行,每行是三种操作之一(1 <= N <= 10^5)
Output
对于每个Q操作,输出一行,答案
Sample Input
6
D 1 100
D 3 8
D 4 10
Q 3 8
C 1
Q 3 8
Sample Output
2
1
Solution
CDQ分治,将删除操作看作插入一条数量为-1的线段,查询操作看作插入一条数量为0的线段,用cnt[i]表示第i次插入的线段被之前插入的线段包含的次数,按操作顺序进行分治,每次统计[l,mid+1]中有多少元素j满足j.y>=i.y,j.x<=i.x,其中mid+1<=i<=r,这个过程可以通过对两个区间都以x为第一关键字降序排,以y为第二关键字升序排,对于[mid+1,r]中的每个i(i为数量为0的元素,即为查询),将[l,mid]中所有满足j.y>=i.y的j以j.x为下标,cnt[j]为键值插入到树状数组中,那么每次只需统计树状数组中下标小于等于i.x的元素键值之和累加到cnt[i]中即可
Code

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;#define maxn 222222int n,h[maxn],tot;struct node{    int x,y,cnt,id,ans;    bool operator <(const node &a)const    {        if(y!=a.y)return y>a.y;        return x<a.x;    }}p[maxn],q[maxn];int cmpid(node a,node b){    return a.id<b.id;}struct BIT {    #define lowbit(x) (x&(-x))    int b[maxn];    void init()    {        memset(b,0,sizeof(b));    }    void update(int x,int v)    {        while(x<=tot)        {            b[x]+=v;            x+=lowbit(x);        }    }    int query(int x)    {        int ans=0;        while(x)        {            ans+=b[x];            x-=lowbit(x);        }        return ans;    }}bit;void CDQ(int l,int r){    if(l==r)return ;    int mid=(l+r)>>1;     CDQ(l,mid);    CDQ(mid+1,r);    sort(p+l,p+mid+1);    sort(p+mid+1,p+r+1);    int j=l;    for(int i=mid+1;i<=r;i++)    {        for(;j<=mid&&p[j].y>=p[i].y;j++)            bit.update(p[j].x,p[j].cnt);        if(!p[i].cnt)p[i].ans+=bit.query(p[i].x);    }    for(int i=l;i<j;i++)bit.update(p[i].x,-p[i].cnt);    merge(p+l,p+mid+1,p+mid+1,p+r+1,q);    for(int i=0;i<r-l+1;i++)p[l+i]=q[i];;}int res,l[maxn],r[maxn];int main(){    while(~scanf("%d",&n))    {        bit.init();        res=1,tot=0;        for(int i=1,j=0;i<=n;i++)        {            p[i].id=i,p[i].ans=0;            char s[3];int temp;             scanf("%s",s);            if(s[0]=='D')            {                scanf("%d%d",&p[i].x,&p[i].y);                p[i].cnt=1;                l[res]=p[i].x,r[res++]=p[i].y;                h[++tot]=p[i].x,h[++tot]=p[i].y;            }            else if(s[0]=='Q')            {                scanf("%d%d",&p[i].x,&p[i].y);                p[i].cnt=0;                h[++tot]=p[i].x,h[++tot]=p[i].y;            }            else             {                scanf("%d",&temp);                p[i].x=l[temp],p[i].y=r[temp];                p[i].cnt=-1;            }        }        sort(h+1,h+tot+1);        tot=unique(h+1,h+tot+1)-h-1;        for(int i=1;i<=n;i++)        {            p[i].x=lower_bound(h+1,h+tot+1,p[i].x)-h;            p[i].y=lower_bound(h+1,h+tot+1,p[i].y)-h;        }           CDQ(1,n);        sort(p+1,p+n+1,cmpid);        for(int i=1;i<=n;i++)            if(!p[i].cnt)printf("%d\n",p[i].ans);    }    return 0;}
0 0
原创粉丝点击