题目链接:点击链接
操作一和操作三是基础的单点更新。
操作二的查询,需要查询连续区间的长度,建树的时候要对每个节点对应的区间[l, r]记录从l开始向右的最大连续区间,长度为prefix,从r开始向左的最大连续区间,长度为suffix,记录中间的最大连续区间,长度为medium。
push up操作。当前节点的medium值为左区间medium,右区间medium,左区间suffix和右区间prefix,三个值的最大者。prefix等于左区间prefix值,当左区间prefix值等于左区间长度时,说明左区间和右区间prefix相邻,当前prefix等于左区间prefix加右区间prefix。suffix同理。
单点查询如何转换成区间查询?查询的时候,在整个区间缩小为一个点的过程中,判断目标点是否在当前区间的连续区间内,如果在,我们再查询该连续区间的端点。(相当于感染)这样就可以查找到目标点所在的连续区间。
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 60000;
stack<int> s;
struct Node
{
int medium;
int prefix;
int suffix;
}tree[maxn<<2];
void pushup(int rt, int len){
int left_interval = (len - len/2);
int right_interval = len / 2;
if(tree[rt<<1].prefix==left_interval)
tree[rt].prefix = tree[rt<<1].prefix+tree[rt<<1|1].prefix;
else
tree[rt].prefix = tree[rt<<1].prefix;
if(tree[rt<<1|1].suffix==right_interval)
tree[rt].suffix = tree[rt<<1].suffix+tree[rt<<1|1].suffix;
else
tree[rt].suffix = tree[rt<<1|1].suffix;
tree[rt].medium = max(tree[rt<<1].medium, tree[rt<<1|1].medium);
tree[rt].medium = max(tree[rt<<1].suffix+tree[rt<<1|1].prefix, tree[rt].medium);
}
void build(int rt, int l, int r){
if(l==r){
tree[rt].prefix = tree[rt].suffix = tree[rt].medium = 1;
}
else{
int mid = (l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
pushup(rt, r-l+1);
}
}
void update(int rt, int idx, int l, int r, int x){
if(l==r && l==idx){
tree[rt].medium = tree[rt].prefix = tree[rt].suffix = x;
}
else{
int mid = (l+r)>>1;
if(idx<=mid) update(rt<<1, idx, l, mid, x);
if(idx>mid) update(rt<<1|1, idx, mid+1, r, x);
pushup(rt, r-l+1);
}
}
int query(int rt, int idx, int l, int r){
if(l==r || tree[rt].medium==0 ||tree[rt].medium == (r-l+1)){
return tree[rt].medium;
}
else{
int mid = (l+r)>>1;
if(idx<=mid){
if(idx>=mid-tree[rt<<1].suffix+1)
return query(rt<<1, idx, l, mid) + query(rt<<1|1, mid+1, mid+1, r);
else
return query(rt<<1, idx, l, mid);
}
if(midif(idx<=mid+1+tree[rt<<1|1].prefix-1)
return query(rt<<1, mid, l, mid) + query(rt<<1|1, idx, mid+1, r);
else
return query(rt<<1|1, idx, mid+1, r);
}
}
}
int main(){
int n, q, x;
char opt[10];
while(scanf("%d%d", &n, &q)!=EOF){
while(!s.empty()) s.pop();
build(1, 1, n);
for(int i=0; iscanf("%s", opt);
if(opt[0]=='D'){
scanf("%d", &x);
update(1, x, 1, n, 0);
s.push(x);
}
if(opt[0]=='Q'){
scanf("%d", &x);
printf("%d\n", query(1, x, 1, n));
}
if(opt[0]=='R'){
if(!s.empty()){
update(1, s.top(), 1, n, 1);
s.pop();
}
}
}
}
return 0;
}