链接: link.
题意:
输入n表示n个城市,输入m表示m个操作,有3中操作:
1、D x 表示摧毁第x个城市
2、Q x 表示查询包括x村庄的连续的没被摧毁的城市个数
3、R 表示修复上一个被摧毁的城市
思路:
对于每个,1表示城市没被摧毁,0表示摧毁,对于每个区间lmax表示从区间最左边开始的连续城市,rmax表示从区间最右边开始的连续城市数量,maxx表示该区间的最大连续区间。
每次摧毁城市的时候,找到那个城市,改为0,然后pushup。
pushup函数中当前区间的lmax=左儿子区间的lmax,如果左儿子区间的lmax==左儿子区间的城市数量,那么当前区间的值还要加上右儿子区间的lmax,同理rmax也是这样(具体看代码)。
对于maxx,就等于左儿子的maxx和右儿子的maxx和左儿子的rmax+右儿子的lmax三者的最大值
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <queue>
#include <vector>
#define ll long long
#define T int T;scanf("%d", &T);while(T--)
#define inf 0x7f7f7f7f
using namespace std;
const int maxn = 1000100;
struct node{
ll lmax,rmax;
int l,r;
ll maxx;
}tree[maxn<<2];
ll a[maxn];
int n,m;
void pushup(int index){
tree[index].lmax = tree[index*2].lmax;
if(tree[index*2].lmax==tree[index*2].r-tree[index*2].l+1){ //如果左区间整个都是好的城市,那么index这个区间的lmax要加上右儿子的lmax
tree[index].lmax += tree[index*2+1].lmax;
}
tree[index].rmax = tree[index*2+1].rmax;
if(tree[index*2+1].rmax==tree[index*2+1].r-tree[index*2+1].l+1){ //如果有区间整个都是好的城市,那么index这个区间的rmax要加上左儿子的rmax
tree[index].rmax += tree[index*2].rmax;
}
tree[index].maxx = max(max(tree[index*2].maxx,tree[index*2+1].maxx),tree[index*2].rmax+tree[index*2+1].lmax);
}
void build(int l,int r,int index){
tree[index].l = l;
tree[index].r = r;
if(l==r){
tree[index].lmax=tree[index].rmax=tree[index].maxx=1; //刚开始都是好的城市
return;
}
int mid = (l+r)/2;
build(l,mid,index*2);
build(mid+1,r,index*2+1);
pushup(index);
}
void update(int w,int p,int index){
if(tree[index].l==tree[index].r){
tree[index].lmax=tree[index].rmax=tree[index].maxx=w; //改变城市状态
return;
}
int mid = (tree[index].l+tree[index].r)/2;
if(p<=mid) update(w,p,index*2); //二分找城市
else update(w,p,index*2+1);
pushup(index);
}
ll query(int p,int index){
if(tree[index].maxx==0 || tree[index].l==tree[index].r){ //如果找到城市或者最长连续区间已经是0
return tree[index].maxx;
}
ll ans = 0;
int mid = (tree[index].l+tree[index].r)/2;
if(p<=mid){
if(mid-p+1<=tree[index*2].rmax) //如果左儿子的rmax包含了p点,那么直接加上右儿子的lmax
ans += tree[index*2].rmax+tree[index*2+1].lmax;
else ans += query(p,index*2); //否则搜索左儿子区间
}
else{
if(p-mid<=tree[index*2+1].lmax) //同理
ans += tree[index*2].rmax+tree[index*2+1].lmax;
else ans += query(p,index*2+1);
}
return ans;
}
int main(){
int tt = 1;
int x,y,z;
int ss[100000];
int last = 0;
while(~scanf("%d", &n)){
build(1,n,1);
scanf("%d", &m);
while(m--){
char c;
cin >> c;
if(c=='D'){
scanf("%d", &x);
ss[++last] = x;
update(0,x,1); //破坏城市,把x变为0
}else if(c=='Q'){
scanf("%d", &x);
printf("%lld\n",query(x,1));
}else{
update(1,ss[last--],1); 修城市,把上一个破坏的城市变成1
}
}
printf("\n");
}
return 0;
}