http://acm.hdu.edu.cn/showproblem.php?pid=1540
题意:
给出直线上一系列的村庄,如果相邻村庄都没有被破坏,
则两村庄是连接的,题目给出一系列的破坏操作,对指定号码的村庄进行破坏,
还有一系列的询问操作,询问与指定号码的村庄直接相连或间接相连的村庄有几个,
还有一个修复操作,是对最后破坏的村庄进行修复。
//线段树
定义三个变量:lmax[rt] 表示从左孩子开始的连续区间个数
rmax[rt] 到右孩子截至的连续区间个数
mmax[rt] 整个区间连续的区间个数
col[rt] 表示区间的状态,0表示未必破坏,1表示已被破坏,-1初始状态
因为为连续区间关键步骤是pushdown 里的赋值操作和pushup的更新操作
#include "stdio.h"
#include "string.h"
const int maxn = 50005;
int n,q,x,val;
int stack[maxn],top;
bool vis[maxn];
struct node
{
int col; //表示区间的状态,0表示未必破坏,1表示已被破坏,-1初始状态
int rmax,lmax,mmax; //到右孩子截至的连续区间个数 表示从左孩子开始的连续区间个数 整个区间连续的区间个数
}tree[maxn*4];
int Max( int a,int b )
{
return a>=b?a:b;
}
void pushup( int ld,int rd,int t )
{
int mid = ( ld+rd )>>1;
tree[t].lmax = tree[t<<1].lmax;
tree[t].rmax = tree[t<<1|1].rmax;
tree[t].mmax = Max( tree[t<<1].mmax,tree[t<<1|1].mmax );
if( tree[t<<1].lmax == mid - ld +1 )
{
tree[t].lmax += tree[t<<1|1].lmax;
}
if( tree[t<<1|1].rmax == rd - mid )
{
tree[t].rmax += tree[t<<1].rmax;
}
tree[t].mmax = Max( tree[t].mmax,tree[t<<1].rmax+tree[t<<1|1].lmax);
}
void pushdown( int ld,int rd,int t )
{
if( tree[t].col!=-1 )
{
int mid = ( ld+rd )>>1;
tree[t<<1].col = tree[t<<1|1].col =tree[t].col;
if( tree[t].col==1 )
{
tree[t<<1].lmax = tree[t<<1].rmax = tree[t<<1].mmax = 0;
tree[t<<1|1].lmax = tree[t<<1|1].rmax = tree[t<<1|1].mmax = 0;
}
else
{
tree[t<<1].lmax = tree[t<<1].rmax = tree[t<<1].mmax = mid-ld+1;
tree[t<<1|1].lmax = tree[t<<1|1].rmax = tree[t<<1|1].mmax = rd-mid;
}
tree[t].col = -1;
}
}
void buildtree( int ld,int rd,int t )
{
tree[t].col = -1;
tree[t].rmax = tree[t].lmax = tree[t].mmax = rd-ld+1;
if( ld == rd )
return;
int mid = ( ld+rd )>>1;
buildtree( ld,mid,t<<1 );
buildtree( mid+1,rd,t<<1|1 );
}
void updata( int ld,int rd,int t )
{
if( ld == rd )
{
tree[t].col = val;
tree[t].lmax = tree[t].rmax = tree[t].mmax = ( val?0:1 );
return;
}
pushdown( ld,rd,t );
int mid = ( ld+rd )>>1;
if( x<=mid )
updata( ld,mid,t<<1 );
else
updata( mid+1,rd,t<<1|1 );
pushup( ld,rd,t );
}
int query( int ld,int rd,int t )
{
if( ld == rd || tree[t].mmax==( rd-ld+1 ) || !tree[t].mmax )
{
return tree[t].mmax;
}
int mid = ( ld+rd )>>1;
if( x<=mid )
{
if( x >= mid - tree[t<<1].rmax+1 )
return tree[t<<1].rmax + tree[t<<1|1].lmax;
else
return query( ld,mid,t<<1 );
}
else
{
if( x <= mid + tree[t<<1|1].lmax+1 )
return tree[t<<1].rmax + tree[t<<1|1].lmax;
else
return query( mid+1,rd,t<<1|1 );
}
}
int main()
{
int i;
char ch[3];
while( scanf("%d%d",&n,&q)==2 )
{
top = 0;
memset(vis,0,sizeof(vis));
getchar();
buildtree( 1,n,1 );
for( i=1;i<=q;i++ )
{
scanf("%s",ch);
if( ch[0]=='D' )
{
scanf("%d",&x);
stack[++top] = x;
val = 1;//1为摧毁
if( !vis[x] )
updata(1,n,1);
vis[x] = 1;
}
else if( ch[0]=='Q' )
{
scanf("%d",&x);
printf("%d\n",vis[x]?0:query(1,n,1) );
}
else
{
if( top )
{
x = stack[top--];
val = 0;//0为修复
if( vis[x] )
updata( 1,n,1 );
vis[x] = 0;
}
}
}
}
return 0;
}