问题描述
抗日战争时期,华北平原广大地区进行了广泛的隧道战争。一般来说,通过隧道连接的村庄成一直线。除了两端的两个村外,每个村庄都与两个相邻的村直接相连。
入侵者经常对一些村庄发动袭击,并摧毁其中的部分隧道。八路军指挥官要求提供隧道和村庄的最新连接状态。如果某些村庄被严重隔离,则必须立即恢复连接!
输入项
输入的第一行包含两个正整数n和m(n,m≤50,000),表示村庄和事件的数量。接下来的m行中的每行都描述一个事件。
下面以不同的格式描述了三种不同的事件:
D x:第x个村庄被摧毁。
Q:陆军司令部要求第x个村庄包括其自身直接或间接联系的村庄数。
R:最后被摧毁的村庄被重建。
输出量
在单独的一行中按顺序输出对陆军指挥官要求的答案。
sample input
7 9
D 3
sampl output
题意:一连串的村庄线性排布,D x 摧毁x村庄 R回复最后摧毁的村庄,Q x 询问x村庄左右最大连续的村庄数
线段树维护连续区间。
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+5;
typedef struct Tree
{
int l,r;
int ssum;//此区间内最大连续和
//int sum_;//该节点以下的节点值得总和
int suml;//此区间得左端开始的最大连续和
int sumr;//此区间得右端开始的最大连续和
}Tree;
Tree t[maxn*4];
void pushup(int n){
//t[n].sum_=t[root*2].sum_+t[root*2+1].sum_;
if(t[2*n].suml==t[2*n].r-t[2*n].l+1)
t[n].suml=t[2*n].suml+t[2*n+1].suml;
else
t[n].suml=t[2*n].suml;
if(t[2*n+1].sumr==t[2*n+1].r-t[2*n+1].l+1)
t[n].sumr=t[2*n+1].sumr+t[2*n].sumr;
else
t[n].sumr=t[2*n+1].sumr;
t[n].ssum=max(max(t[n*2].ssum,t[n*2+1].ssum),(t[n*2].sumr+t[n*2+1].suml));
}
void build(int n,int l,int r)
{
t[n].l=l;
t[n].r=r;
if(l==r)
{
//num=root;
t[n].ssum=t[n].suml=t[n].sumr=r-l+1;
// tree[root].ssum=power[left];
// tree[root].suml=power[left];
// tree[root].sum_=power[left];
// tree[root].sumr=power[left];
}
else
{
int mid=(l+r)/2;
build(n*2,l,mid);
build(n*2+1,mid+1,r);
pushup(n);
}
}
int query_sum(int n,int k)
{
if(t[n].l==t[n].r)
return t[n].ssum;
else{
int mid=(t[n].l+t[n].r)/2;
if( k <= mid )
if(k>=t[2*n].r-t[2*n].sumr+1)
return t[2*n].sumr+t[2*n+1].suml;
else
return query_sum(2*n,k);
else {
if( k<=t[2*n+1].l+t[2*n+1].suml-1)
return t[2*n].sumr+t[2*n+1].suml;
else
return query_sum(2*n+1,k);
}
}
}
void update(int n,int pos,int value)
//更新函数就是先不断二分找到位置,然后要像建树一样合并区间
{
if(t[n].l==t[n].r){
t[n].ssum=value;
t[n].suml=value;
// t[n].sum_=value;
t[n].sumr=value;
}
else
{
int mid=(t[n].l+t[n].r)/2;
if(pos<=mid)
update(2*n,pos,value);
else
update(2*n+1,pos,value);
pushup(n);
}
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
char s[5];
int a[maxn];
int x;
int cnt=0;
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%s",s);
if(s[0]==‘D‘){
scanf("%d",&x);
a[cnt++]=x;
update(1,x,0);
}
if(s[0]==‘Q‘){
scanf("%d",&x);
printf("%d\n",query_sum(1,x));
}
if(s[0]==‘R‘){
update(1,a[--cnt],1);
}
}
}
return 0;
}
原文:https://www.cnblogs.com/lyj1/p/11922261.html