码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-08-13 12:19:09      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:树状数组   多校联合   

【题目链接】: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数组不能开小了,否则会RE
int 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;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:树状数组   多校联合   

原文地址:http://blog.csdn.net/u013050857/article/details/47606829

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!