CF1400: 1490E,448B,1462FD,650A,1380B,1451C

1490E. Accidental Victory (dichotomy)

Topic:

A total of n people participated in the competition, each with a strong value.
Pick two PKS at random each time, and the winner gets the strength of the other. If the strength values are the same, win randomly.
Question: Who has the chance to win in the end?

Ideas:

That is to say, who must lose.
The maximum strength a person gets is the sum of all the smaller values.

Fa 1:
Sort everyone from smallest to largest.
The prefix of one location and the value of the next location, if not less, indicate that the current location can outperform the next.
If not, there is no chance of winning in the current position or in all the positions ahead.
Find the last place that won't win.

Fa 2: Binary
Since there is a chance that the current position will win, the next position will win, so you can divide the first position to win.

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m;
PII a[N];

bool check(int mid)
{
	ll sum=a[mid].first;
	for(int i=1;i<=n;i++)
	{
		if(i==mid) continue;
		if(a[i].first<=sum) sum+=a[i].first;
		else return 0; 
	}
	return 1;
}

int main(){
	Ios;
	
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i].first;
			a[i].second=i;
		}
		sort(a+1,a+n+1);
		
		/*Fa 1: 
		ll sum=0,f=0;
		for(int i=1;i<n;i++)
		{
			sum+=a[i].first;
			if(sum<a[i+1].first) f=i;
			
			set<int> st;
			for(int i=f+1;i<=n;i++) st.insert(a[i].second);
			
			cout<<st.size()<<endl;
			for(auto it:st){
				cout<<it<<" ";
			}
			cout<<endl;
		}*/
		
		int l=1,r=n;
		while(l<r)
		{
			int mid=l+r>>1;
			if(check(mid)) r=mid;
			else l=mid+1;
		}
		
		set<int> st;
		for(int i=l;i<=n;i++) st.insert(a[i].second);
		
		cout<<st.size()<<endl;
		for(auto it:st){
			cout<<it<<" ";
		}
		cout<<endl;
	}
	
	return 0;
}

448B. Suffix Structures (double pointer)

Topic:

Given two strings a and b, determine whether a can become B for each of the following operations:
1. Exchange only the position of two characters.
2. Delete only certain characters.
3. Use the first two operations at the same time.

Ideas:

When deciding only to delete, a double pointer is needed to determine that the relative order of the b-string in A-string has not changed.
Exchange only to determine if they occur the same number of times.

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m;
string a,b;

int main(){
	cin>>a>>b;
	n=a.size(),m=b.size();
	a=" "+a,b=" "+b;
	
	int cnt=0;
	for(int i=1,j=1;i<=m;i++)
	{
		while(j<n&&a[j]!=b[i]) j++;
		if(a[j]==b[i]) cnt++,j++;
	}
	if(cnt==m&&n!=m){
		cout<<"automaton";return 0;
	}
	
	for(int i=1;i<=n;i++) mp[a[i]]++;
	
	bool flag=0;
	for(int j=1;j<=m;j++){
		if(!mp[b[j]]){
			flag=1;break;
		}
		mp[b[j]]--;
	}
	if(flag){
		cout<<"need tree";
		return 0;
	}
	
	if(n==m){
		cout<<"array";
	}
	else cout<<"both";
	 
	return 0;
}

1462D. Add to Neighbour and Remove (think, enumerate answers)

Topic:

Given a column of length n, how many times are the elements of each location equal?
Select a location I and add the value of ai to the location i-1 or i+1; Delete location i, followed by elements.

Ideas:

In fact, the above operation is to merge several consecutive locations into a single location and turn them into a new array.
Make all merged elements the same. So we can enumerate the values that all the last elements become.
But the whole range is too big.

However, 1~i locations must be merged into one location, so we can enumerate the number of locations I of the first combination.
Let the values of this group be the values of all the last elements to see if they work. If possible, the answer takes the smallest operand.

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m, a[N];
ll sum;
int ans;

void check(int m)
{
	sum=0;
	for(int i=1;i<=m;i++) sum+=a[i];
	
	ll t=0;int cnt=m-1;
	for(int i=m+1;i<=n;i++)
	{
		t+=a[i];cnt++;
		if(sum==t) t=0,cnt--;
		else if(t>sum) return;
	}
	if(t!=0) return;
	ans=min(ans,cnt);
}

int main(){
	Ios;
	
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		
		ans=1e9;
		for(int len=1;len<=n;len++)
		{
			check(len);
		}
		cout<<ans<<endl;
	}
	
	return 0;
}

650A. Watchmen (combination)

Topic:

Given several points, how many pairs of points do two distances give the same result?

Ideas:

Simplified equation, (xi-xj)(yi-yj)=0.
So the pairs of points that are satisfied either have the same x, the same y, or the same.

So you can find the point logarithm that satisfies the same logarithm of x + the same logarithm of y, and subtract the point logarithm that both x and y are the same.

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m, a[N];

int main(){
	Ios;
	
	cin>>n;
	for(int i=1;i<=n;i++){
		int p,q;cin>>p>>q;
		x[p]++,y[q]++;
		mp[{p,q}]++;
	}
	
	ll ans=0;
	for(auto it:x){
		ll cnt=it.second;
		ans+=cnt*(cnt-1)/2;
	}
	for(auto it:y){
		ll cnt=it.second;
		ans+=cnt*(cnt-1)/2;
	}
	for(auto it:mp){
		ll cnt=it.second;
		ans-=cnt*(cnt-1)/2;
	}
	cout<<ans;
	
	return 0;
}

Now it comes to mind to deform the formula first.

1380B. Universal Solution (thinking)

Topic:

Given a string a, three characters: RSP, corresponding to stone, scissors, cloth.
You can start a loop from one location and output.
Construct a string B and output it from 1, so that a string starts to loop from n positions, and the average number of wins is the largest from the string b-order output.

Ideas:

All characters in the construction string b are the enemy of the most characters in the a string.
The number of characters that appear more often in a string is harvested each time.

Make bold assumptions!!

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m;
string a;

int main(){
	Ios;
	
	cin>>T;
	while(T--)
	{
		cin>>a;
		int cnt1=0,cnt2=0,cnt3=0;
		for(int i=0;i<a.size();i++)
		{
			if(a[i]=='R') cnt1++;
			else if(a[i]=='S') cnt2++;
			else cnt3++;
		}
		int maxa=max(cnt1,max(cnt2,cnt3));
		char c;
		if(cnt1==maxa) c='P';
		else if(cnt2==maxa) c='R';
		else c='S';
		
		for(int i=0;i<a.size();i++) cout<<c;
		cout<<endl;
	}
	
	return 0;
}

1451C. String Equality

Topic:

Given strings a,b of length n. Given length m. Determine if string a can be transformed into string b by doing the following?

  • Swap the position of two characters. or

  • Select a substring whose length is m and all elements are the same, and add all its elements + 1. (example'b'becomes'c')

Ideas:

Because the positions can be arbitrarily transformed, the positions of consecutive elements are the same regardless.
The number of occurrences of each element in strings a and b is counted separately.
Traverse through each element in string a to determine if its number is greater than m:
If so, the number of the first larger character in b can be subtracted by m;
If not, you need a character in b that is the same as the character. If not, not required.

Finally, determine whether the elements in b have been removed, the number is zero. If not, it does not meet the requirements.

Code:

const int N = 1000010, mod = 1e9+7;
int T, n, m;
char a[N],b[N];
char c[N],d[N];

int main(){
	Ios;
	
	cin>>T;
	while(T--)
	{
		mp1.clear();mp2.clear();
		cin>>n>>m;
		cin>>a+1;
		cin>>b+1;
		
		sort(a+1,a+n+1);
		sort(b+1,b+n+1);
		
		for(int i=1;i<=n;i++) mp1[a[i]]++;
		for(int i=1;i<=n;i++) mp2[b[i]]++;
		
		int ans=0;
		for(auto it:mp1)
		{
			while(it.second>=m)
			{
				bool flag=0;
				for(int i=it.first-'a';i<26;i++)
				{
					char c='a'+i;
					if(mp2[c]>=m){
						mp2[c]-=m;
						flag=1;
						break;
					}
				}
				if(!flag){
					ans=-1;break;
				}
				it.second-=m;
			}
			if(ans==-1) break;
			if(it.second)
			{
				if(mp2[it.first]>=it.second) mp2[it.first]-=it.second;
				else{
					ans=-1;break;
				}
			}
		}
		
		for(auto it:mp2){
			if(it.second) ans=-1;
		}
		
		if(ans==-1) cout<<"No\n";
		else cout<<"Yes\n";
	}
	
	return 0;
}

Posted by robin339 on Tue, 02 Nov 2021 12:56:02 -0700