您的位置:首页 > 其它

hdu5372Segment Game 树状数组

2015-11-04 20:18 302 查看
//n个输入
//a[i] b[i]  a[i] = 0 , 加上线段[b[i],b[i]+x] , x为加操作的个数
//a[i] = 1 减去第b[i]个加入的线段
//问对于每一个新加的区间能够包括有多少完整的区间
//可以知道线段的长度是递增的,所以原来的区间的长度没有大于现在的
//所以只要求原来的所有区间的左区间大于新加的减去右边大的
//然后由于|b[i]|<=1e9
//所以先将其离线,然后排个序,用二分找
#include<cstdio>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std ;
const int maxn = 2e5+10 ;
int tree[2][maxn]  ;
int a[maxn] , b[maxn]  ;
int l[maxn] , r[maxn] ;
int ssl[maxn] , ssr[maxn] ;
int n ;
int getsum(int x , int pp)
{
int sum = 0 ;
while(x)
{
sum += tree[pp][x] ;
x -= x&(-x) ;
}
return sum ;
}
void update(int x , int dx , int pp)
{
while(x <= n)
{
tree[pp][x] += dx;
x += x&(-x) ;
}
}
int main()
{
//    freopen("d:\\in.txt" , "r"  ,stdin) ;
int cas = 0 ;
while(~scanf("%d" , &n))
{
for(int i = 1;i <= n;i++)
tree[0][i] = tree[1][i] = 0 ;
int len = 1;
int len_l = 0 ;
int len_r = 0 ;
for(int i = 1;i <= n;i++)
{
scanf("%d%d" , &a[i] , &b[i]) ;
if(!a[i])
{
l[len_l++] = b[i] ;
r[len_r++] = b[i] + len ;
len++ ;
}
}
sort(l , l+len_l) ;
len_l = unique(l , l + len_l) - l ;
sort(r , r+len_r) ;
len_r = unique(r , r+len_r) - r ;
len =  1 ;
int sum = 0 ;
printf("Case #%d:\n"  , ++cas) ;
for(int i = 1;i <= n;i++)
if(!a[i])
{
int pos_l = lower_bound(l ,  l + len_l , b[i]) - l  + 1 ;
int pos_r = lower_bound(r ,  r + len_r , b[i]+len) - r + 1 ;            int x = sum - getsum(pos_l - 1 , 0) ;
int y = sum - getsum(pos_r , 1) ;
update(pos_l , 1 , 0) ;
update(pos_r , 1 , 1) ;
ssl[len] = pos_l ;
ssr[len] = pos_r  ;
len++ ;
sum++ ;
printf("%d\n" , x - y)  ;
}
else
{
update(ssl[b[i]] , -1 , 0) ;
update(ssr[b[i]] , -1 , 1) ;
sum-- ;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: