题意
有一段连续的序列 [ 1 , 2 , 3 , . . . , n ] [1,2,3,...,n] [1,2,3,...,n],有3种操作
- 删除数字 K K K, K K K的两边断开
- 询问数字 K K K 所在的连续段的长度(若 K K K被删除则长度为0)
- 回撤上一次删除操作
题解
有两种做法
- 线段树区间合并,记录区间的最长左连续段长度和最长右连续段长度
- 平衡树记录删除的结点,询问的答案就是 K K K的后继-前驱-1
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
const int mod = 1e9+7;
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;
struct node{
int l,r,mid;
int llen,rlen;
}seg[N];
void pushup(int rt){
seg[rt].llen=seg[rt<<1].llen+(seg[rt<<1].llen==seg[rt<<1].r-seg[rt<<1].l+1?seg[rt<<1|1].llen:0);
seg[rt].rlen=seg[rt<<1|1].rlen+(seg[rt<<1|1].rlen==seg[rt<<1|1].r-seg[rt<<1|1].l+1?seg[rt<<1].rlen:0);
}
void build(int rt,int l,int r){
int mid=l+r>>1;
seg[rt].l=l,seg[rt].mid=mid,seg[rt].r=r,seg[rt].llen=1,seg[rt].rlen=1;
if(l==r)return ;
build(rt<<1,l,mid),build(rt<<1|1,mid+1,r);
pushup(rt);
}
void update(int rt,int pos,int val){
if(seg[rt].l==seg[rt].r){ seg[rt].llen=seg[rt].rlen=val; return ; }
update(rt<<1|(pos>seg[rt].mid),pos,val);
pushup(rt);
}
int query(int rt,int pos){
if(seg[rt].l==seg[rt].r) return seg[rt].llen;
if(pos<=seg[rt].mid){
if (pos>=seg[rt<<1].r-seg[rt<<1].rlen+1) return seg[rt<<1].rlen+seg[rt<<1|1].llen;
return query(rt<<1,pos);
}
else{
if(pos<=seg[rt<<1|1].l+seg[rt<<1|1].llen-1) return seg[rt<<1|1].llen+seg[rt<<1].rlen;
return query(rt<<1|1,pos);
}
}
#define endl '\n'
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,q;
while(cin>>n>>q){
stack<int>sk; while(!sk.empty()) sk.pop();
build(1,1,n);
while(q--){
string s; cin>>s;
if(s=="D"){ int p; cin>>p; update(1,p,0); sk.push(p); }
if(s=="R"){ update(1,sk.top(),1); sk.pop(); }
if(s=="Q"){ int p; cin>>p; cout<<query(1,p)<<endl; }
}
}
}
(有现成的set不会有人手写平衡树吧
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
const int mod = 1e9+7;
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
#define endl '\n'
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,q;
while(cin>>n>>q){
set<int>st;
stack<int>s;
st.insert(0);
st.insert(n+1);
for(int i=1;i<=q;i++){
char op; int k; cin>>op;
if(op=='D')cin>>k,st.insert(k),s.push(k);
if(op=='Q'){
cin>>k;
if(st.find(k)!=st.end())cout<<0<<endl;
else{
auto l=st.lower_bound(k),r=st.lower_bound(k);
cout<<*r-*--l-1<<endl;
}
}
if(op=='R')st.erase(s.top()),s.pop();
}
}
}