题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1540
思路:
1.注意一下恢复的情况,村庄可以被破坏多次,只需要一次就可以恢复
2.最大连续区间 注释很详细了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 5e4+10;
struct node{
int l,r;
int ms,ls,rs;
// ls是左区间的长度,rs是右区间长度,ms是区间里面的最大长度
int mid() {
return (l+r)/2;
}
};
node num[N*4];
void build( int root,int l,int r )
{
num[root].l = l ;
num[root].r = r;
num[root].ms = num[root].ls = num[root].rs = r-l+1;
if ( l==r ) return ;
build( root*2, l,num[root].mid() );
build( root*2+1, num[root].mid()+1 , r );
return ;
}
void update( int root,int pos,int op ) {
if ( num[root].l==num[root].r ) {
num[root].ls = num[root].rs = num[root].ms = op ;
return ;
}
if ( pos<=num[root].mid() ) update( root*2,pos,op );
else update( root*2+1,pos,op ) ;
num[root].ls = num[root*2].ls; //root左区间 是左子树的左区间的长度
num[root].rs = num[root*2+1].rs; //root右区间 是右子树的右区间的长度
if ( num[root*2].r-num[root*2].ls+1==num[root*2].l )
num[root].ls += num[root*2+1].ls; //如果左子树的区间长度覆盖整个左子树的长度,它就和右子树的左区间连在了一起,所以加上右子树的左区间
if ( num[root*2+1].r-num[root*2+1].rs+1==num[root*2+1].l )
num[root].rs += num[root*2].rs;
num[root].ms = max( max( num[root*2].ms,num[root*2+1].ms) , num[root*2].rs+num[root*2+1].ls );
return ;
}
int query( int root,int pos )
{
//如果区间的最大长度是0 或者 查找到了根节点 或者 区间最大连续长度就是整个区间的长度 就返回
if ( num[root].ms==0 || (num[root].ms==num[root].r-num[root].l+1) || num[root].l==num[root].r )
return num[root].ms;
if ( pos<=num[root].mid() ) {
//如果pos在左子树的右区间里面,那么它的连续长度需要加上右子树的第一个值的连续长度.
if ( pos>=num[root*2].r-num[root*2].rs+1 )
return query( root*2,pos ) + query( root*2+1,num[root].mid()+1 ) ;
// return query( root*2,pos ) + num[root*2+1].ls ; 和上一句是一模一样的效果
else return query( root*2,pos );
}
else {
if ( pos <= num[root*2+1].l+num[root*2+1].ls-1 )
return query( root*2+1,pos ) + query( root*2,num[root].mid() ) ; ///mid-1
// return query( root*2+1,pos ) + num[root*2].rs ; 和上一句是一模一样的效果
else return query( root*2+1,pos );
}
}
int n,q;
bool vis[N];
int s[N];
int top=0;
char c;
int main()
{
int temp,ans;
while ( scanf("%d%d",&n,&q)!=EOF ) {
memset( vis,false,sizeof(vis) );
top = 0; //!!!!!
build( 1,1,n);
while ( q-- ) {
scanf(" %c",&c);
if ( c=='D' ) {
scanf("%d",&temp);
vis[temp] = 1;
s[top++] = temp;
update( 1,temp,0 );
}
else if ( c=='R' ) {
temp = s[--top];
if ( vis[temp] ) {
update( 1,temp,1 ) ;
vis[temp] = 0;
}
else temp = s[--top];
}
else {
scanf("%d",&temp);
ans = query( 1,temp ) ;
cout<<ans<<endl ;
}
}
}
return 0 ;
}
本文提供了一道 HDU 1540 的算法题解,使用了线段树来求解最大连续区间的问题。通过构建线段树并进行更新和查询操作,实现了对村庄破坏状态的有效跟踪。
208

被折叠的 条评论
为什么被折叠?



