HDU1540
线段树最大连续区间。
给定长度为n的数组,m次操作。
操作D,删除给定节点。
操作R,恢复最后一个删除的节点。
操作Q,询问给定节点的最大连续区间
维护三个值,区间的最大左连续区间,最大右连续区间,最大连续区间
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn = 50000 + 5;
#define lson l,m,st<<1
#define rson m+1,r,st<<1|1
int treelmax[maxn<<2];
int treermax[maxn<<2];
int len[maxn<<2];
void build(int l,int r,int st)
{
len[st]=r-l+1;
if(l==r)
{
treelmax[st]=1;treermax[st]=1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
treelmax[st]=len[st]; //初始化的值全为区间长度
treermax[st]=len[st];
}
void UpdataDes(int x,int l,int r,int st) //破坏
{
if(l==x&&r==x)
{
treelmax[st]=0; treermax[st]=0;len[st]=0; return;
}
int m=(l+r)>>1;
if(x<=m) UpdataDes(x,lson);
else UpdataDes(x,rson); //if(x>m)
treelmax[st]=treelmax[st<<1]==(m-l+1)?treelmax[st<<1]+treelmax[st<<1|1]:treelmax[st<<1]; //判断左儿子的最大左连续区间是否等于左儿子区间长度,如果等于,那么父亲的最大左连续区间就等于左儿子的区间长度加上右儿子右最大左区间连续长度
treermax[st]=treermax[st<<1|1]==(r-m)?treermax[st<<1|1]+treermax[st<<1]:treermax[st<<1|1];
len[st]=max(max(treelmax[st<<1],treermax[st<<1|1]),treermax[st<<1]+treelmax[st<<1|1]);
//父节点的最大连续长度等于 左儿子最大左连续区间 右儿子最大右连续区间 左儿子最大右连续区间加上右儿子最大左连续区间 中的最大值
}
void UpdataRec(int x,int l,int r,int st) //修复
{
if(l==x&&r==x)
{
treelmax[st]=1; treermax[st]=1;len[st]=1; return ;
}
int m=(l+r)>>1;
if(x<=m) UpdataRec(x,lson);
else UpdataRec(x,rson); //if(x>m)
treelmax[st]=treelmax[st<<1]==(m-l+1)?treelmax[st<<1]+treelmax[st<<1|1]:treelmax[st<<1];
treermax[st]=treermax[st<<1|1]==(r-m)?treermax[st<<1|1]+treermax[st<<1]:treermax[st<<1|1];
len[st]=max(max(treelmax[st<<1],treermax[st<<1|1]),treermax[st<<1]+treelmax[st<<1|1]);
//pushup;
}
int query(int x,int l,int r,int st)
{
if(l==r||len[st]==0||len[st]==r-l+1)
return len[st];
int m=(l+r)>>1;
if(x<=m) //x在左儿子区间内
{
if(x>=m-treermax[st<<1]+1) //x在左儿子的右连续区间内
return treermax[st<<1]+treelmax[st<<1|1]; //左儿子右连续
//return len[st<<1];
else //x在左儿子的左连续区间内
return query(x,lson);
}
else //x在右儿子区间内
{
if(x<m+1+treelmax[st<<1|1]) //x在右儿子的左连续区间
return treermax[st<<1]+treelmax[st<<1|1]; //左儿子的右连续加上右儿子的左连续
//return len[st<<1|1];
else //x在右儿子的右连续区间
return query(x,rson);
}
}
int main()
{
int n,m;
char ope[5];
int x;
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,n,1);
stack<int> destroy;
while(m--)
{
scanf("%s",ope);
if(ope[0]=='D')
{
scanf("%d",&x);
UpdataDes(x,1,n,1);
destroy.push(x);
}
else if(ope[0]=='R')
{
if(destroy.empty()) continue;
x=destroy.top();
UpdataRec(x,1,n,1);
destroy.pop();
}
else
{
scanf("%d",&x);
printf("%d
",query(x,1,n,1));
}
}
}
return 0;
}