codeforces-1450D-Rating Compression (monotonic stack)

Main idea:

Give you n numbers. For each length len (1<=len<=n), is the set consisting of the minimum value of (n-i+1) a full array? It is represented by 1, not 0 Means

Question idea:

1. Use the monotonic stack to find the current a[i] controllable range l[i], r[i] - the monotonic stack to find the maximum value of the interval
2. If the number num in the set of length len is the first occurrence, Then use the tree array to
check tree[num]++ and check whether query(n-i+1) is greater than or equal to n-i+1 to know that the current length len does not meet the conditions

Specific operation:

When traversing ans[i], we must go backwards.
Take this set of examples 1 3 3 2
because we are looking for the maximum range of the left and right interval that can be controlled.
If we go up and look for len[1], no one can find it. Yes, but len=1 is eligible,
but if you traverse backwards,
first find Len=3, num = 1 .tree[1]++ ,check — ok
len=2, num =2 ,3 .tree[2] ++,tree[3]++ ,check—ok
len =1 without check —ok

Code:

int l[maxn],r[maxn],a[maxn],n,ans[maxn],vis[maxn],b[maxn];
int t[maxn];
vector<int>len[maxn];
int lowbit(int x) {
    
    
	return x&(-x);
}
void add(int x) {
    
    
	while(x<=n) t[x]++,x+=lowbit(x);
}
int q(int x) {
    
    
	int ans=0;
	while(x>0) {
    
    
		ans+=t[x];
		x-=lowbit(x);
	}
	return ans;
}
int main() {
    
    
	int _  = read();
	while(_--) {
    
    
		mst(vis,0);
		n=read();
		rep(i,1,n) a[i] = read(), ans[i]= t[i] =l[i] = r[i] = 0,len[i].clear();
		stack<int>st;

		for(int i=1 ; i<=n ; i++) {
    
    
			while(st.size()&&a[i]<=a[st.top()])st.pop();
			if(st.size()==0) l[i] = 1;
			else l[i] = st.top()+1;
			st.push(i);
		}
		while(st.size()) st.pop();


		for(int i= n ; i>=1 ; i--) {
    
    
			while(st.size()&&a[i]<=a[st.top()]) st.pop();
			if(st.size()==0) r[i] = n;
			else r[i] = st.top()-1;
			st.push(i);
		}
		while(st.size()) st.pop();

		rep(i,1,n) len[r[i]-l[i]+1].push_back(a[i]);

		for(int i=n ; i>=1 ; i--) {
    
    
			for(int num:len[i]) {
    
    
				vis[num]++;
				if(vis[num]==1) add(num);
			}
			int sum = q(n-i+1);
			if(sum>=n-i+1) ans[i] =1;
		}
		rep(i,1,n) cout<<ans[i];
		cout<<endl;
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/wmy0536/article/details/110941490