PKU 2892 [HDU 1540]

Tunnel Warfare

题型:线段树

描述:n个村子排成一条线,两两相邻,1.摧毁村子c,2.修复上一次摧毁的村子,3.问与村子c直接或间接相通的村子数

思路:对节点的操作,增加lx,rx域,表示区间内最左边被摧毁的村子,和最右边被摧毁的村子,s表示区间内摧毁的村子总数。

重点在count(),统计相连村子数操作。根据父结点的两个孩子结点的 s 值,讨论各种可能情况。

if (t[k0].s == 0) {
if (t[k0+1].s == 0) cnt = t[k].r-t[k].l+1;
else if (t[k0+1].lp > a) cnt = t[k0].r-t[k0].l+1+t[k0+1].lp-t[k0+1].l;
else count(a, k0+1);
}
else {
if (t[k0+1].s == 0 && t[k0].rp < a)
cnt
= t[k0+1].r-t[k0+1].l+1+t[k0].r-t[k0].rp;
else if (a>t[k0].rp && a<t[k0+1].lp)
cnt
= t[k0].r-t[k0].rp + t[k0+1].lp-t[k0+1].l;
else {
if (a <= md) count(a, k0);
else count(a, k0+1);
}
}

 

完整代码
//234MS 2804K
#include <stdio.h>
#include
<string.h>
#define NL 65536

struct Seg {
int l, r;
int lp, rp, s;
}t[NL
*2];
bool dt[50001];//1 没被摧毁 0 被摧毁
int stk[50001];
int cnt;

void build(int l, int r, int k)
{
t[k].l
= l;
t[k].r
= r;
t[k].s
= 0;
t[k].lp
= t[k].rp = 0;
if (l == r) dt[l] = 1;
int md = (l+r)>>1, k0 = k<<1;
if (l < r) {
build(l, md, k0);
build(md
+1, r, k0+1);
}
}
//flg = 0 摧毁,flg = 1 恢复
void mody(int a, int k, bool flg)
{
if (t[k].l == t[k].r) {
if (flg) t[k].s = 0, dt[a] = 1;
else {
t[k].s
= 1;
t[k].lp
= t[k].rp = a;
dt[a]
= 0;
}
return;
}
int md = (t[k].l+t[k].r)>>1, k0 = k<<1;
if (a <= md)
mody(a, k0, flg);
else if (a > md)
mody(a, k0
+1, flg);
t[k].s
= t[k0].s + t[k0+1].s;
if (t[k].s) {
t[k].lp
= t[k0].lp;
t[k].rp
= t[k0+1].rp;
if (t[k0].s == 0) t[k].lp = t[k0+1].lp;
if (t[k0+1].s == 0) t[k].rp = t[k0].rp;
}
}

void count(int a, int k)
{
if (t[k].l == t[k].r) {
cnt
= 1;
return;
}
int md = (t[k].l+t[k].r)>>1, k0 = k<<1;
if (t[k0].s == 0) {
if (t[k0+1].s == 0) cnt = t[k].r-t[k].l+1;
else if (t[k0+1].lp > a) cnt = t[k0].r-t[k0].l+1+t[k0+1].lp-t[k0+1].l;
else count(a, k0+1);
}
else {
if (t[k0+1].s == 0 && t[k0].rp < a)
cnt
= t[k0+1].r-t[k0+1].l+1+t[k0].r-t[k0].rp;
else if (a>t[k0].rp && a<t[k0+1].lp)
cnt
= t[k0].r-t[k0].rp + t[k0+1].lp-t[k0+1].l;
else {
if (a <= md) count(a, k0);
else count(a, k0+1);
}
}
}

int main()
{
int n, m, a, top;
char c[3];
// freopen("in.txt", "r", stdin);
while (scanf("%d%d", &n, &m) != EOF) {
build(
1, n, 1);
top
= 0;
while (m--) {
scanf(
"%s", c);
if (c[0] == 'D') {
scanf(
"%d", &a);
stk[top
++] = a;
mody(a,
1, 0);
}
else if (c[0] == 'Q') {
scanf(
"%d", &a);
cnt
= 0;
if (dt[a])
count(a,
1);
printf(
"%d\n", cnt);
}
else {
a
= stk[--top];
mody(a,
1, 1);
}
}
}
return 0;
}

 

posted @ 2010-07-18 17:43  superbin  阅读(426)  评论(0编辑  收藏  举报