比赛链接:https://codeforces.ml/contest/1779

这次比赛还行吧,蓝名表现分上青了。D题有点虐,可以用dp、单调栈、rmq、树状数组、并查集做。我一个也没想到,现在弄明白了单调栈做法和rmq做法。感觉E题说不定能出,随便看两眼D题没思路,直接开E了

A水 B水但是恶心 C思路很简单就是很麻烦,两个堆来维护。

D题:

大意是给出数组a,给出数组b。给出m种操作。每次可以将a数组中的l -r  中的ai 替换成 ai = min(ai, x)。x来源于m种。

询问是否可以由a得到b。

记录每个数在b中出现的位置。如果存在bi>ai肯定no。
否则。我们去列举每个数出现的位置。如果存在相邻位置,那么操作数-1,如果两个位置中最大的数就是这个数,那么操作数-1.
找两个位置中最大的数我们可以用st表去处理这些数据。

rmq code:

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	map<int,int> mp;
	cin>>m;
	int tx;
	for(int i=1;i<=m;i++){
		cin>>tx;
		mp[tx]++;
	} 
	
	for(int i=1;i<=n;i++){
		if(a[i]<b[i]) {
			cno;
			return;
		}
	}
	
	ST_init();
	map<int,vector<int>>ve;
	for(int i=1;i<=n;i++){
		if(b[i]!=a[i]){
			ve[b[i]].push_back(i);
		}
	}
	for(auto iter = ve.begin();iter!=ve.end();iter++){
		int t = iter->first;
		vector<int> vv = iter->second; 
		int cur = vv.size();
		for(int i=0;i<vv.size()-1;i++){
			int x = vv[i],y=vv[i+1];
			if(x==y-1) cur--;
			else{
				int mx = stquery(x+1,y-1);
				if(mx<=t) cur--;
			}
		}
		if(cur>mp[t]){
			cno;
			return;
		}
	}
	cyes;
}

 

另一种做法也是比较普遍的做法就是单调栈。

这个题我们可以用单调栈去维护数据。顺序处理这些数据。如果该数比栈顶元素大。那些小的数就没有作用了。

最后栈顶如果和当前一样,我们继续保留之前的,这次不进行操作。因为进行上次操作时已经可以操作当前的数。

否则我们进行操作一次。因为之前可操作的大的数无法操作当前数。

单调栈 code:

void solve()
{
	mp.clear();
	int n,m;
	ll x;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	cin>>m;
	for(int i=1;i<=m;i++){
		cin>>x;
		mp[x]++;
	}
	stack<ll> st;
	for(int i=1;i<=n;i++){
		if(a[i]<b[i]){
			cno;
			return;
		}
		while(!st.empty()&&st.top()<b[i]) st.pop();
		if((st.empty()||st.top()!=b[i])&&a[i]!=b[i]){
			st.push(b[i]);
			if(mp[b[i]]<=0){
				cno;
				return;
			}
			mp[b[i]]--;
		}
	}
	cyes;
}