Codeforces Good Bye 2021: 2022 is NEAR ABCDE

A. Integer Diversity

Count the number of figures with different absolute values in all figures. Only when the number of absolute values is less than 2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=200100;
int n,m,t;
int w[N];
int cw[N];
int main(){
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		for( int i=0;i<n;i++){
			scanf("%d",&w[i]);
		}
		multiset<int>se;
		for( int i=0;i<n;i++){
			int x=abs(w[i]);
			if(x!=0)
				if(se.count(x)<2)se.insert(x);
			if(x==0)
				if(se.count(x)<1) se.insert(x);
		}
		cout<<se.size()<<endl;
		
	}
}

B. Mirror in the String

Classification discussion: when there are two identical letters at the beginning of a string, directly output the two beginning letters, otherwise output a monotonically decreasing character sequence until a monotonically increasing sequence is encountered.
Mapping analysis will be clearer.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=200100;
int n,m,t;
int w[N];
int cw[N];
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		string s;
		cin>>s;
		string ans;
		ans+=s[0];
		int flag=0;
		for( int i=1;i<s.size();i++){
			if(s[i]<*(--ans.end())){
				ans+=s[i];
				flag=1;
			}
			else if(s[i]==*(--ans.end())){
				if(flag==0) break;
				else ans+=s[i];
			}
			else break;
		}
		cout<<ans;
		reverse(ans.begin(),ans.end());
		cout<<ans<<endl;
	}
	return 0;
}

C. Representative Edges

Enumerate any two points in the sequence, then calculate the slope, judge how many points are on the straight line, and pay attention to the accuracy.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=200100;
int n,m,t;
int w[N];
int cw[N];
int eq(double x,double y){
	return fabs(x-y)<1e-7;
}
int check( double x,int val,int pos){
	int res=0;
	for( int i=0;i<n;i++){
		if(eq(1.0*w[i]-val,x*(i-pos))) ;
		else res++;
	}
	return res;
}
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		
		for( int i=0;i<n;i++){
			scanf("%d",&w[i]);
		}
		if(n==1){
			cout<<0<<endl;
			continue;
		}
		int ans=inf;
		for( int i=0;i<n;i++){
			for( int j=0;j<i;j++){
				double div=(1.0*w[i]-w[j])/(i-j);
				ans=min(ans,check(div,w[i],i));
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

D. Keep the Average High

Main idea of the topic: divide an interval into any sub interval, and each sub interval meets:
The average value of any sub interval in this interval is greater than x

Status dp
Just discuss the last two choices and no choices, a total of four cases.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=200100;
int n,m,t;
int w[N];
int dp[N][4];//00 0 means that the last two are not selected, 01 1 means the last one, 10 2 means, 11 3 means
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for( int i=1;i<=n;i++){
			scanf("%d",&w[i]);	
		}
		int x;
		cin>>x;
		for( int i=1;i<=n;i++){
			dp[i][0]=max(dp[i-1][0],dp[i-1][2]);
			dp[i][1]=max(dp[i-1][0],dp[i-1][2])+1;
			dp[i][2]=max(dp[i-1][1],dp[i-1][3]);

			if(i==1) {
				dp[i][3]=1;
			}
			else if(i==2){
				if(w[i]+w[i-1]>=x+x) dp[i][3]=2;
				else dp[i][3]=-inf;
			}
			else{
				if(w[i]+w[i-1]>=x+x&&w[i]+w[i-1]+w[i-2]>=x+x+x)
					dp[i][3]=max(dp[i-1][1],dp[i-1][3])+1;
				else if(w[i]+w[i-1]>=x+x)
					dp[i][3]=dp[i-1][1]+1;
				else dp[i][3]=-inf;
			}
		}
		int ans=0;
		for( int i=0;i<4;i++){
			ans=max(dp[n][i],ans);
		}
		cout<<ans<<endl;
		
	}
}

E. Lexicographically Small Enough

Data structure.
If the previous bits are equal, there are two strategies to obtain the minimum value. The first strategy is to replace the standard with a smaller value than the original, and the second strategy is to replace the standard with the same value as the original bit, and then recursion.
If violence is implemented, the entire array needs to be facilitated once at a time, and the time complexity is n*n
You can use set optimization to find the nearest number that is larger or equal to the original number in the time of logn.
However, when two numbers are equal, the position of the number will change due to exchange, so a data structure is needed to maintain this change.
There are many maintenance methods, such as tree array, line segment tree, balance tree, etc.
Here, a balanced tree is used to record the original position of each exchange number. For each query, you only need to find that several numbers in the back are exchanged to the front to calculate the change of position.
Note the need to open longlong

#include <bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const ll inf=1e15;
const int N=200100;
int n,m,q;
string s,t;
int cnt[26];
tree<int,null_type,greater<int>,rb_tree_tag,tree_order_statistics_node_update>delete_pos;
int f(int x){
	return x+delete_pos.order_of_key(x);
}
signed main(){
	cin>>q;
	while(q--){
		cin>>n>>s>>t;
		memset(cnt,0,sizeof(cnt));
		delete_pos.clear();
		set<int>se[26];
		for( int i=0;i<s.size();i++){
			cnt[s[i]-'a']++;
			se[s[i]-'a'].insert(i);
		}
		ll ans=inf,cnt_swap=0;
		for( int i=0;i<t.size();i++){
			int x=t[i]-'a',y=s[i]-'a';
			int flag=0;
			for( int j=0;j<x;j++){
				if(cnt[j]){
					ans=min(ans,cnt_swap+f(*se[j].begin())-i);
					flag=1;
				}
			}
			if(cnt[x]){
				flag=1;
				int posx=*se[x].begin(),posy=*se[y].begin();
				delete_pos.insert(posx);
				cnt_swap+=f(posx)-i;
				se[x].erase(se[x].begin());
				cnt[x]--;
			}
			else break;
			if(flag==0){
				break;
			}
		}
		if(ans==inf) printf("-1\n");
		else printf("%lld\n",ans);
		endd:;
	}	
	return 0;
}

Keywords: C++ Algorithm data structure Dynamic Programming CodeForces

Added by jibosh on Wed, 05 Jan 2022 03:22:05 +0200