CodeForces

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;
}

  

原文地址:https://www.cnblogs.com/lesning/p/13895111.html