http://poj.org/problem?id=2892
题意:在抗日时期,我方经常采用地道战,地雷战,麻雀战来袭扰日军。
现在n个村子一开始是全部联通的,假设成一条直线。
给出3种操作 D x x村庄的地道被日本鬼子炸毁 (炸毁之后地道无法相连)
Q x 问有与x相连的村庄最长的长度 假设一个村为一个长度单位
R 修复日本鬼子最近一个炸毁的村庄的地道 (最近指时间最近)
做法:用线段树来维护三个值,ls,lr,ms, ls是对一个区间从最左端起连续的地道长度
rs是对一个区间从最右端起连续的地道长度
ms是对一个区间最长的连续的地道长度
用栈来存储日本鬼子炸毁的地道,以便后续修复。
询问一次查找一次。输出结果
代码:
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <math.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
#define mem(a) memset(a,0,sizeof(a));
#define mem_1(a) memset(a,-1,sizeof(a));
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define lson l,mid,root << 1
#define rson mid+1,r,root << 1|1
const int INF = 0x7FFFFFFF;
const int MAXN = 50100;
const double PI = acos(-1.0);
const double esp = 1e-10;
using namespace std;
struct node
{
int l,r,ls,rs,ms;
int mid()
{
return (l+r)>>1;
}
}Tree[MAXN<<2];
int s[MAXN<<1];
void build_tree(int l,int r,int root)
{
Tree[root].l = l;
Tree[root].r = r;
Tree[root].ls = Tree[root].rs = Tree[root].ms = r - l +1;
if(l == r) return ;
int mid = Tree[root].mid();
build_tree(lson);
build_tree(rson);
}
void updata_tree(int t,int root,int k)
{
if(Tree[root].l == Tree[root].r)
{
if(k == 1)
Tree[root].ls = Tree[root].rs = Tree[root].ms = 1;
else
Tree[root].ls = Tree[root].rs = Tree[root].ms = 0;
return ;
}
int mid = Tree[root].mid();
if(t <= mid) updata_tree(t,root<<1,k);
else updata_tree(t,root<<1|1,k);
Tree[root].ls = Tree[root<<1].ls;
Tree[root].rs = Tree[root<<1|1].rs;
Tree[root].ms = max(max(Tree[root<<1].ms,Tree[root<<1|1].ms),
Tree[root<<1].rs + Tree[root<<1|1].ls);
if(Tree[root << 1].ls == Tree[root << 1].r - Tree[root<<1].l +1)
{
Tree[root].ls = Tree[root<<1].ls+Tree[root <<1|1].ls;
}
if(Tree[root << 1|1].rs == Tree[root<<1|1].r - Tree[root<<1|1].l +1)
{
Tree[root].rs = Tree[root<<1|1].rs + Tree[root<<1].rs;
}
}
int Query(int root,int t)
{
if(Tree[root].l == Tree[root].r ||
Tree[root].ms==0 ||
Tree[root].ms == Tree[root].r - Tree[root].l +1)
return Tree[root].ms;
int mid = Tree[root].mid();
if(t<=mid)
{
if(t >= Tree[root << 1].r - Tree[root<<1].rs +1)
return Query(root << 1,t) + Query(root<<1|1,mid+1);
else
return Query(root << 1,t);
}
else
{
if(t<=Tree[root<<1|1].l + Tree[root<<1|1].ls-1)
return Query(root<<1|1,t) + Query(root<<1,mid);
else
return Query(root<<1|1,t);
}
}
int main()
{
int i,j,x,n,m,top;
char c[2];
while(~sff(n,m))
{
top = 0;
build_tree(1,n,1);
while(m--)
{
scanf("%s",c);
if(c[0] == 'D')
{
sf(x);
s[top++] = x;
updata_tree(x,1,0);
}
else if(c[0] == 'Q')
{
sf(x);
printf("%d\n",Query(1,x) );
}
else
{
if(x>0)
{
x = s[--top];
updata_tree(x,1,1);
}
}
}
}
return 0;
}
本文介绍了一种使用线段树解决地道战模拟问题的方法。通过维护三个值(ls, lr, ms)来更新和查询区间内连续的地道长度。利用栈记录被破坏的地道,以便进行回溯修复。
674

被折叠的 条评论
为什么被折叠?



