您的位置:首页 > 其它

区间合并 连续性问题 查询与第x个村相连的村子有多少个

2015-10-11 18:04 281 查看
题目链接  hdu1540 Tunnel Warfare

题目大意:有N个村子排成一条直线,每个村子都连接了它的左右两个村子(除了最左边和最右边的外),有3种操作,(1)"D x",表示将第x个村子摧毁。(2)"Q x",表示查询与第x个村子直接和间接相连的村子有多少个。(3)"R",表示将最早摧毁的村子复原。

解题思路:O(-1)

#include <cstdio>
#include <vector>
#include <map>
#include <iostream>
using namespace std;

#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=50005;
int flag[4*maxn];
int stack[maxn];
int top;

struct segment
{
int lm;
int rm;
int sm;
} tree[4*maxn];

void push_up(int u, int l, int r)
{
int mid= (l+r)>>1;
tree[u].lm= tree[u*2].lm;
tree[u].rm= tree[u*2+1].rm;
tree[u].sm= max( tree[u*2].sm, tree[u*2+1].sm );
if( tree[u*2].lm == mid-l+1 ) tree[u].lm += tree[u*2+1].lm;
if( tree[u*2+1].rm == r-mid ) tree[u].rm += tree[u*2].rm;
int t= tree[u*2].rm + tree[u*2+1].lm;
if( t > tree[u].sm ) tree[u].sm= t;
}

void build(int u, int l, int r)
{
flag[u]=-1;
if(l==r)
{
tree[u].lm= tree[u].rm= tree[u].sm= 1;
return;
}
int mid= (l+r)>>1;
build(lz);
build(rz);
push_up(u, l, r);
}

void Update(int u, int l, int r, int pos, int c)
{
if(l==r)
{
tree[u].lm=tree[u].rm=tree[u].sm=c;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) Update(lz,pos,c);
else Update(rz,pos,c);
push_up(u,l,r);
}

int Query(int u, int l, int r, int p)
{
if(tree[u].sm==r-l+1) return tree[u].sm;
if(l==r) return 0;
int mid=(l+r)>>1;
if(mid-tree[2*u].rm+1<=p&&p<=mid+tree[2*u+1].lm)
return tree[2*u].rm+tree[2*u+1].lm;
else if(p<=mid) return Query(lz,p);
else return Query(rz,p);
}

int main()
{
int n, m, op;
while(cin >> n >> m)
{
map<int,int>mp;
top=0;
build(1,1,n);
while(m--)
{
char ch[5];
scanf("%s",ch);
if(ch[0]=='D')
{
scanf("%d",&op);
Update(1,1,n,op,0);
stack[++top]=op;
}
else if(ch[0]=='R')
{
if(top) Update(1,1,n,stack[top--],1);
}
else
{
scanf("%d",&op);
int ans=Query(1,1,n,op);
printf("%d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: