您的位置:首页 > 其它

[kuangbin带你飞]专题七 线段树 I HDU 1540

2016-09-22 19:27 411 查看
题目地址:https://vjudge.net/contest/66989#problem/I

思路:建树是用ls,rs,ms,分别代表该区间内从左端点开始的最长连续区间,从右端点开始的,以及整个区间内的。对于每个区间,初始化时显然为r-l+1。在更新时,以T[k]为例,显然他的ls最小为T[2*k]区间的ls,如果他的ls等于整个区间的长度,说明他与T[2*k+1]相连,则加上T[2*k+1]的ls。同理,rs的更新也是一样的判断。而ms,首先他至少为2*k,2*k+1的ms中的最大者。然后将这个值与将2*k,2*k+1的rs,ls相加再比较,这就得到了k的新ms。

而查询时,相对简单一些,但是在递归查找时也一样,要考虑是否相连,当与另一侧相连时,同样需要加上对应的ls或者rs。线段树好难啊……这种操作比较复杂的题目还是只能敲个build就滚粗了……思路参考了kuangbin大神的题解,随便百度一下就有了。还有个这题要用EOF,我真没看到题目哪里说了啊……

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
struct seq{
int l,r,ls,rs,ms;//左侧开始的最大连续区间,右侧开始的最大连续空间,区间内最长连续空间
}T[maxn*4];

void build(int l,int r,int k)
{
T[k].l=l,T[k].r=r;
T[k].ls=T[k].rs=T[k].ms=r-l+1;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}

void update(int n,int k,int v)
{
if(T[k].l==n && T[k].r==n)
{
if(v)//摧毁
T[k].ls=T[k].rs=T[k].ms=0;
else
T[k].ls=T[k].rs=T[k].ms=1;
return;
}
else
{
int mid=(T[k].l+T[k].r)>>1;
if(n<=mid)
update(n,k<<1,v);
else if(n>mid)
update(n,k<<1|1,v);
T[k].ls=T[k<<1].ls;
T[k].rs=T[k<<1|1].rs;
T[k].ms=max(T[k<<1].ms,T[k<<1|1].ms);
T[k].ms=max(T[k].ms,T[k<<1].ls+T[k<<1|1].rs);
if(T[k<<1].ls==T[k<<1].r-T[k<<1].l+1) T[k].ls+=T[k<<1|1].ls;//判断左右连续区间是否相连
if(T[k<<1|1].rs==T[k<<1|1].r-T[k<<1|1].l+1) T[k].rs+=T[k<<1].rs;
}
}

int search(int n,int k)
{
if(T[k].l==T[k].r || T[k].ms==0 || T[k].ms==T[k].r-T[k].l+1)
{
return T[k].ms;
}
int mid=(T[k].r+T[k].l)>>1;
if(n<=mid)
{
if(n>=T[k<<1].r-T[k<<1].rs+1)//相连
return search(n,k<<1)+search(mid+1,k<<1|1);
else
return search(n,k<<1);
}
else
{
if(n<=T[k<<1|1].l+T[k<<1|1].ls-1)
return search(n,k<<1|1)+search(mid,k<<1);
else
return search(n,k<<1|1);
}
}

int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
stack<int>k;
memset(T,0,sizeof(T));
build(1,n,1);
while(m--)
{
char a[2];
scanf("%s",a);
if(a[0]=='D')
{
int a;
scanf("%d",&a);
k.push(a);
update(a,1,1);
}
else if(a[0]=='Q')
{
int a;
scanf("%d",&a);
printf("%d\n",search(a,1));
}
else if(a[0]=='R')
{
int a;
a=k.top();
k.pop();
update(a,1,0);
}
}
}

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