您的位置:首页 > 其它

hdu 1540 Tunnel Warfare(线段树区间合并)

2014-05-13 19:49 411 查看
hdu 1540 Tunnel Warfare

记录每个节点的最大左连续值、最大右连续值、最大连续值,向上更新的是常规的区间合并处理方式

关键是想到如何去查询,如果查询节点落在左儿子节点的右连续段中,则代表右儿子节点的左连续段也要算上,同样的如果查询节点落在右儿子的左连续段中,则代表左儿子的右连续段也要算上

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define MAXN 50005
#define lch p<<1
#define rch p<<1|1
#define mid (t[p].l+t[p].r)>>1
struct node
{
int l,r;
int lmx,mx,rmx;
int getlen() {return r-l+1;}
}t[MAXN*4];
void construct(int l,int r,int p)
{
t[p].l=l,t[p].r=r;
t[p].lmx=t[p].rmx=t[p].mx=t[p].getlen();
if(l==r) return ;
int m=mid;
construct(l,m,lch);
construct(m+1,r,rch);
}
int max(int a,int b) {return a>b?a:b;}
void pushup(int p)
{
t[p].mx=max(t[lch].mx,t[rch].mx);
t[p].mx=max(t[p].mx,t[lch].rmx+t[rch].lmx);

t[p].lmx=t[lch].lmx;
if(t[lch].mx==t[lch].getlen()) t[p].lmx+=t[rch].lmx;

t[p].rmx=t[rch].rmx;
if(t[rch].mx==t[rch].getlen()) t[p].rmx+=t[lch].rmx;
}
void modify(int x,int p,int v)
{
if(t[p].l==t[p].r)
{
t[p].lmx=t[p].rmx=t[p].mx=v;
return ;
}
int m=mid;
if(x<=m) modify(x,lch,v);
else modify(x,rch,v);
pushup(p);
}
int query(int x,int p)
{
if(t[p].l==t[p].r||
t[p].mx==0||
t[p].mx==t[p].getlen())
return t[p].mx;

int m=mid;
if(x<=m)
{
if(t[lch].r-t[lch].rmx+1<=x)
return query(x,lch)+query(m+1,rch);
else return query(x,lch);
}
else
{
if(t[rch].l+t[rch].lmx-1>=x)
return query(x,rch)+query(m,lch);
else return query(x,rch);
}
}
stack<int> stc;
int main()
{
int n,m,x;
char op[3];
while(scanf("%d%d",&n,&m)!=EOF)
{
construct(1,n,1);
while(!stc.empty()) stc.pop();
while(m--)
{
scanf("%s",op);
if(op[0]=='D')
{
scanf("%d",&x);
modify(x,1,0);
stc.push(x);
}
else if(op[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(x,1));
}
else
{
if(!stc.empty())
{
modify(stc.top(),1,1);
stc.pop();
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 区间合并