您的位置:首页 > 其它

hdu5372 Segment Game (树状数组)

2016-02-24 00:28 246 查看
题意:每次插入一条线段或删除之前一条线段,每次操作线段长度递增,求插入一段线段时有多少线段被它完全覆盖。

由于保证线段长度递增,我们可以用右断点在合法区间内的减去左端点不在合法区间的,可以用树状数组分开维护。

下标需要离散化。

下标可以是负数,这读入优化坑了我一个小时。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<assert.h>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
#define clr(x) memset(x,0,sizeof x)
#define LL long long
const int inf = 0x3f3f3f3f;
const int MAXN = 700005;
int N;

void get(int&r)
{
char c, f=0;r=0;
do{ c=getchar();if(c=='-')f=1;} while(c<'0'||c>'9');
do r=r*10+c-'0',c=getchar(); while(c>='0'&&c<='9');
if (f) r=-r;
}

int c1[MAXN*2], c2[MAXN*2];
void add(int *c, int i, int x)
{
for (; i<MAXN*2; i+=i&-i)
c[i] += x;
}
int qsum(int*c, int i)
{
int r = 0;
for (; i>0; i-=i&-i)
r += c[i];
return r;
}

int b[MAXN], to[MAXN];
int d1[MAXN], d2[MAXN];
int dat[MAXN*2], dn;
int idx(int x) { return lower_bound(dat+1,dat+dn+1,x) - dat; }
int main()
{
int cid = 0, len;
while (~scanf("%d", &N))
{
memset(c1, 0, sizeof c1);
memset(c2, 0, sizeof c2);
len = dn = 0;
rep(i, 1, N)
{
get(d1[i]), get(d2[i]);
if (d1[i] == 0)
{
++len;
dat[++dn] = d2[i];
dat[++dn] = d2[i] + len;
}
}
printf("Case #%d:\n", ++cid);
len = 0;
sort(dat+1, dat+dn+1);
dn = unique(dat+1,dat+dn+1)-dat-1;
rep(i, 1, N)
{
if (d1[i] == 0)
{
++len;
to[len] = idx(d2[i] + len);
b[len] = idx(d2[i]);
assert(dat[to[len]] == d2[i]+len);
assert(dat[b[len]] == d2[i]);
printf("%d\n", qsum(c2, to[len]) - qsum(c1, b[len]-1));
add(c1, b[len], 1), add(c2, to[len], 1);
}
else
{
add(c1, b[d2[i]], -1);
add(c2, to[d2[i]], -1);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: