HDU 5372 Segment Game (MUT#7 树状数组+离散化)

来源:互联网 发布:顾家家居怎么样知乎 编辑:程序博客网 时间:2024/06/07 16:25

【题目链接】:click here~~

【题目大意】:

题意:两种操作,添加线段和删除线段,第i次添加时告诉线段起点并且要添加长度为i的线段,删除第i次添加的线段,问每次添加后有多少线段是落在当前要画的线段内部的。

【思路】:比赛的时候居然直接无视了这道题,赛后看了一下,感觉要用到树状数组,有一种前后互相影响的样子,昨天想了一下午,加上昨天晚上,总算是搞明白了,因为每次画的线段的长度是递增的,所以当前画的线段不可能被其他线段包含,那么统计小于左端点的点的个数x和小于等于右端点的点的个数y,两者之差就是所求答案。树状数组维护一下,值得注意的是因为坐标数据较大,所以提前离散化处理一下,所谓离散化,就是把原来的输入用一定操作改成数据之间差值较小换句话来说就是比较连续,而且操作完之后的数据大小关系满足之前的关系,T_T,树状数组好神奇~

代码:

/*对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点。再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案。时间复杂度nlogn*/#include <iostream>#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N=4e5+10;int bit[2][N];int t,n,m;typedef pair<int ,int >pii;pii pir[N];int ans,cnt,tot,len;int L[N],R[N],op[N];/// op数组不能开小了,否则会REint pos[N];int lowbit(int x){return x&(-x);}int sum(int i,int p){    int s=0;    while(i>0){        s+=bit[p][i];        i-=lowbit(i);    }    return s;}void add(int i,int x,int p){/// p:0 maintain left 1 the right    while(i<=N){        bit[p][i]+=x;        i+=lowbit(i);    }}int main(){    tot=1;    while(~scanf("%d",&t)){        cnt=0;len=0;        memset(bit,0,sizeof(bit));memset(op,0,sizeof(op));memset(L,0,sizeof(L));        memset(R,0,sizeof(R));memset(pos,0,sizeof(pos));        for(int i=1; i<=t; ++i){            scanf("%d%d",&op[i],&L[i]);/// operation and left point            if(op[i]==0){                R[i]=L[i]+(++cnt); /// update the right point                pos[len++]=L[i];   ///                pos[len++]=R[i];            }        }        cnt=0;        sort(pos,pos+len);        len=unique(pos,pos+len)-pos;///Remove consecutive duplicates in range        for(int i=1; i<=t; ++i){///Discrete            if(op[i]==0){                L[i]=lower_bound(pos,pos+len,L[i])-pos+1;///The first position is greater than or equal to L[i]                R[i]=lower_bound(pos,pos+len,R[i])-pos+1;///The first position is greater than R[i]                pir[++cnt]=make_pair(L[i],R[i]);            }        }        printf("Case #%d:\n",tot++);        for(int i=1; i<=t; ++i){            if(op[i]==0){                printf("%d\n",sum(R[i],1)-sum(L[i]-1,0));/// the difference between L[i] and R[i]                add(L[i],1,0);add(R[i],1,1);            }            else{                add(pir[L[i]].first,-1,0);/// remove the range of L[i]                add(pir[L[i]].second,-1,1);///remove the range of R[i]            }        }    }    return 0;}



0 0