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 ;
}

 

你可能感兴趣的:(HDU)