您的位置:首页 > 其它

线段树--区间合并--HDU 1540

2016-08-10 19:11 357 查看
题意:

题意:D: 破坏村庄,R:修复最后一个破损的村庄,Q:查找X在内的连续区间值有多少

思路:

建立线段树,维护左右区间值。注意维护变量为: 从左编开始最大连续值,从右边开始最大值,最大连续值 

为了维护最后一个被破坏的。需要时刻记录,并且不能只单纯记录一个,而是需要记录顺序。满足先入后出的栈操作,传参即可 #include <iostream>
#define lson i<<1,left,mid
#define rson i<<1|1,mid+1,right
#include <stdio.h>
#include <cstring>
using namespace std;
#define maxn 50010

int s[maxn],top;
int n,m;
struct TreeNode
{
int left;
int right;
int ls,rs,ms;
}a[maxn*3];
void Build(int i,int left,int right)
{
a[i].ls=a[i].rs=a[i].ms=right-left+1;
a[i].left=left;
a[i].right=right;
if(left==right)
return ;
int mid=(left+right)>>1;
Build(lson);
Build(rson);
}
void insert(int i,int t,int x)
{
if(a[i].left==a[i].right)
{
if(x==1)
a[i].ls=a[i].rs=a[i].ms=1;
else
a[i].ls=a[i].rs=a[i].ms=0;
return ;
}
int mid=(a[i].left+a[i].right)>>1;
if(t<=mid)
insert(i<<1,t,x);
else
insert(i<<1|1,t,x);

a[i].ls=a[i<<1].ls;
a[i].rs=a[i<<1|1].rs;
a[i].ms=max(max(a[i<<1].ms,a[i<<1|1].ms),a[i<<1].rs+a[i<<1|1].ls);
if(a[i<<1].ls==a[i<<1].right-a[i<<1].left+1)
a[i].ls+=a[i<<1|1].ls;
if(a[i<<1|1].rs==a[i<<1|1].right-a[i<<1|1].left+1)
a[i].rs+=a[i<<1].rs;
}
int query(int i,int t)
{
if(a[i].left==a[i].right||a[i].ms==a[i].right-a[i].left+1)
return a[i].ms;
int mid=(a[i].left+a[i].right)>>1;
if(t<=mid)
{
if(t>=a[i<<1].right-a[i<<1].rs+1)
return query(i<<1,t)+query(i<<1|1,mid+1);
else
return query(i<<1,t);

}
else
{
if(t<=a[i<<1|1].left+a[i<<1|1].ls-1)
return query(i<<1|1,t)+query(i<<1,mid);
else
return query(i<<1|1,t);
}
}int main()
{
int i,j,x;
char ch[2];
while(~scanf("%d%d",&n,&m))
{
top = 0;
Build(1,1,n);
while(m--)
{
scanf("%s",ch);
if(ch[0] == 'D')
{
scanf("%d",&x);
s[top++] = x;
insert(1,x,0);
}
else if(ch[0] == 'Q')
{
scanf("%d",&x);
printf("%d\n",query(1,x));
}
else
{
if(x>0)
{
x = s[--top];
insert(1,x,1);
}
}
}
}

return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: