您的位置:首页 > 其它

Hdu 5372 Segment Game (树状数组)

2015-08-12 17:21 274 查看
题目链接:

  Hdu 5372 Segment Game

题目描述:

  有一段区间,对这段区间有两种操作。1:插入操作,第i次插入长度为i的线段,并询问被当前线段完全覆盖的线段数目。

                   2:删除操作,删除第b次插入的线段。

解题思路:

  对于当前新插入线段,只需要统计已插入线段中右端点小于该线段右端点的数目,以及左端点小于该线段做端点的数目,两者相减即可。还有就是离散化问题,sort+unique+map真的是离散化利器(啧啧啧~)。

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 200005;
typedef long long LL;
struct opera
{
int a, l, r;
}p[maxn];
int cl[maxn], cr[maxn], al[maxn], ar[maxn], L[maxn];
//树状数组不能从0开始
int lowbit (int x)
{
return x & (-x);
}

int sum (int x, int a[])
{
int Sum = 0;
while (x > 0)
{
Sum += a[x];
x -= lowbit(x);
}
return Sum;
}

void change (int i, int x, int a[], int n)
{
while (i <= n)
{
a[i] += x;
i += lowbit(i);
}
}

int main ()
{
int n, m, cnt, t, cas = 0;
while (scanf ("%d", &t) != EOF)
{
memset (cl, 0, sizeof(cl));
memset (cr, 0, sizeof(cr));
n = m = cnt = 0;

for (int i=0; i<t; i++)
{
scanf ("%d %d", &p[i].a, &p[i].l);
if (p[i].a == 0)
{
cnt ++;
p[i].r = p[i].l + cnt;
al[n++] = p[i].l;
ar[m++] = p[i].r;
L[cnt] = p[i].l;
}
}

sort (al, al+n);
n = unique (al, al+n) - al;
sort (ar, ar+m);
m = unique (ar, ar+m) - ar;
map <int, int> ml, mr;

for (int i=0; i<n; i++)
ml[al[i]] = i + 1;
for (int i=0; i<m; i++)
mr[ar[i]] = i + 1;

cnt = 0;
printf ("Case #%d:\n", ++cas);
for (int i=0; i<t; i++)
{
if (p[i].a)
{

int left = ml[L[p[i].l]];
int right = mr[L[p[i].l]+p[i].l];
change (left, -1, cl, n);
change (right, -1, cr, m);
}
else
{
int ansl = sum (ml[p[i].l]-1, cl);
int ansr = sum (mr[p[i].r], cr);
printf ("%d\n", ansr - ansl);
change (ml[p[i].l], 1, cl, n);
change (mr[p[i].r], 1, cr, m);
}
}
}
return 0;
}


好久没有写过树状数组了,基本忘光光>_<.....,今天算是从新温习了一下(感觉这个代码好渣,改天再改一下)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: