https://codeforces.com/problemset/problem/1436/E
这个题是个线段树
问你子串的mex 的mex
如果子串 的mex没有4,则没有办法分割出 存在1 存在2 存在3 不存在4 的字串出来,所以可以枚举,当前数字是list[i],记录之前list[i]出现位置为pos
利用权值线段树查询1 -- list[i]-1的最小下标是不是大于pos就可以判断了。
#include<iostream> #include<queue> #include<vector> #include<algorithm> using namespace std; const int maxn = 2e5+11; int tree[maxn*4]; int n; int update(int node,int be,int en,int i,int val) { int mid = be + en >>1; int l = node*2; int r = node*2+1; if(be == en) { tree[node] = val; return 0; } if(i <= mid) update(l,be,mid,i,val); else update(r,mid+1,en,i,val); tree[node] = min(tree[l] ,tree[r]); return 0; } int ask(int node,int be,int en,int LL,int RR) { int mid = be + en >>1; int l = node*2; int r = node*2+1; if(LL <= be && en <= RR) { return tree[node]; } int val1 =1e9,val2 = 1e9; if(LL <= mid) val1 = ask(l,be,mid,LL,RR); if(RR > mid) val2 = ask(r,mid+1,en,LL,RR); return min(val1,val2); } int vis[maxn]; int ans[maxn]; int list[maxn]; int main() { int len; cin>>n; for(int i=1; i<=n; i++) { update(1,1,n,i,-1); cin>>list[i]; if(list[i] != 1) ans[1] = 1; } //ans表示可以 for(int i=1;i<=n;i++){ if(list[i] == 1){ vis[list[i]] = i; update(1,1,n,1,i); } else{ int mid = ask(1,1,n,1,list[i]-1); if(mid > vis[list[i]]){ ans[list[i]] |= 1; } vis[list[i]] = i; update(1,1,n,list[i],i); } } for(int i=2;i<=n+1;i++){ int mid = ask(1,1,n,1,i-1); if(mid > vis[i]){ ans[i] |= 1; } } for(int i=1;i<=n+3;i++){ if(ans[i] == 0){ cout<<i<<endl; break; } } return 0; }