题解(646.div2)

题解(646.div2)

A:Odd Selection

Shubham has an array a of size n and wants to select exactly x elements from it, such that their sum is odd. These elements do not have to be consecutive. The elements of the array are not guaranteed to be distinct.
Tell him whether he can do so.
Input
The first line of the input contains a single integer t (1≤t≤100) — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers n and x (1≤x≤n≤1000) — the length of the array and the number of elements you need to choose.
The next line of each test case contains nn integers a1,a2,…,an (1≤ai≤1000) — elements of the array.
Output
For each test case, print “Yes” or “No” depending on whether it is possible to choose x elements such that their sum is odd.
You may print every letter in any case you want.

这道题是一道数学题,需要根据奇偶数得出算法,就能快速解决。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(int x){
	if(x<2)return 0;
	for(int i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
using namespace std;
int t,x,n;
int main(){
	cin>>t;
	while(t--){
		int js=0,os=0;
		cin>>n>>x;
		for(int i=0,tmp;i<n;i++){
			cin>>tmp;
			if(tmp%2)js++;
			else os++;
		}
		if(n<x||js==0){
			cout<<"No\n";
			continue;
		}
		x--,js--;
		if(n<=os){
			cout<<"Yes\n";
			continue;
		}
		else if(x%2){
			if(os==0){
				cout<<"No\n";
				continue;
			}
			os--,x--;
		}
		x-=js/2*2;
		if(x<=os)cout<<"Yes\n";
		else cout<<"No\n";
	}
	return 0;
}

B:Subsequence Hate

Shubham has a binary string ss. A binary string is a string containing only characters “0” and “1”.
He can perform the following operation on the string any amount of times:
Select an index of the string, and flip the character at that index. This means, if the character was “0”, it becomes “1”, and vice versa.
A string is called good if it does not contain “010” or “101” as a subsequence — for instance, “1001” contains “101” as a subsequence, hence it is not a good string, while “1000” doesn’t contain neither “010” nor “101” as subsequences, so it is a good string.
What is the minimum number of operations he will have to perform, so that the string becomes good? It can be shown that with these operations we can make any string good.
A string a is a subsequence of a string b if a can be obtained from b by deletion of several (possibly, zero or all) characters.
Input
The first line of the input contains a single integer tt (1≤t≤100) — the number of test cases.
Each of the next t lines contains a binary string s (1≤|s|≤1000).
Output
For every string, output the minimum number of operations required to make it good.

同样,这道数学题是根据0,1来得出算法。首先把01数量统计,然后用根据题目要求得出的算法计算。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(int x){
	if(x<2)return 0;
	for(int i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
int main(){
	int t=read();
	while(t--){
		char s[1500];
		cin>>s;
		int ls=0,ys=0,ans=0x7f7f7f7f;
		for(int i=0;i<strlen(s);i++){
			if(s[i]=='0')ls++;
			else ys++;
		}
		for(int i=0;i<strlen(s);i++){
			ans=min(ans,min(ls,ys));
			if(s[i]=='0')ls--,ys++;
			else ys--,ls++;
		}
		cout<<ans<<endl;
	} 
	return 0;
}



C:Game On Leaves

Ayush and Ashish play a game on an unrooted tree consisting of nn nodes numbered 1 to n. Players make the following move in turns:
Select any leaf node in the tree and remove it together with any edge which has this node as one of its endpoints. A leaf node is a node with degree less than or equal to 1.
A tree is a connected undirected graph without cycles.
There is a special node numbered x. The player who removes this node wins the game.
Ayush moves first. Determine the winner of the game if each player plays optimally.
Input
The first line of the input contains a single integer t (1≤t≤10) — the number of testcases. The description of the test cases follows.
The first line of each testcase contains two integers n and x (1≤n≤1000,1≤x≤n) — the number of nodes in the tree and the special node respectively.
Each of the next n−1 lines contain two integers u,v (1≤u,v≤n, u≠v), meaning that there is an edge between nodes u and v in the tree.
Output
For every test case, if Ayush wins the game, print “Ayush”, otherwise print “Ashish” (without quotes).

这道题是一道与图论结合的博弈题。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(int x){
	if(x<2)return 0;
	for(int i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
int main(){
    int t=read();
	while(t--){
		int tre[2000]={},n=read(),x=read();
		for(int i=1;i<n;i++){
			tre[read()]++,tre[read()]++;
		}
		if(tre[x]<=1){
			cout<<"Ayush"<<endl;
		}else{
			if(n%2)cout<<"Ashish"<<endl;
			else cout<<"Ayush"<<endl;
		}
	}
	return 0;
}

D:Guess The Maximums

This is an interactive problem.
Ayush devised a new scheme to set the password of his lock. The lock has k slots where each slot can hold integers from 1 to n. The password P is a sequence of k integers each in the range [1,n], i-th element of which goes into the i-th slot of the lock.
To set the password of his lock, Ayush comes up with an array A of n integers each in the range [1,n] (not necessarily distinct). He then picks k non-empty mutually disjoint subsets of indices S1,S2,…,Sk (Si∩i≠jSj=∅) and sets his password as Pi=maxj∉SiA[j]. In other words, the ii-th integer in the password is equal to the maximum over all elements of A whose indices do not belong to Si.
You are given the subsets of indices chosen by Ayush. You need to guess the password. To make a query, you can choose a non-empty subset of indices of the array and ask the maximum of all elements of the array with index in this subset. You can ask no more than 12 queries.
Input
The first line of the input contains a single integer tt (1≤t≤10) — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers n and k (2≤n≤1000,1≤k≤n) — the size of the array and the number of subsets. k lines follow. The i-th line contains an integer c (1≤c<n) — the size of subset Si, followed by c distinct integers in the range [1,n] — indices from the subset Si.
It is guaranteed that the intersection of any two subsets is empty.
Interaction
To ask a query print a single line:
In the beginning print "? c " (without quotes) where c (1≤c≤n) denotes the size of the subset of indices being queried, followed by c distinct space-separated integers in the range [1,n].
For each query, you will receive an integer x — the maximum of value in the array among all the indices queried. If the subset of indices queried is invalid or you exceeded the number of queries (for example one of the indices is greater than n) then you will get x=−1. In this case, you should terminate the program immediately.
When you have guessed the password, print a single line "! " (without quotes), followed by k space-separated integers — the password sequence.
Guessing the password does not count towards the number of queries asked.
After this, you should read a string. If you guess the password correctly, you will receive the string “Correct”. In this case, you should continue solving the remaining test cases. If the guessed password is incorrect, you will receive the string “Incorrect”. In this case, you should terminate the program immediately.
The interactor is not adaptive. The array A does not change with queries.
After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:
fflush(stdout) or cout.flush() in C++;
System.out.flush() in Java;
flush(output) in Pascal;
stdout.flush() in Python;
see documentation for other languages.
Hacks
To hack the solution use the following test format:
The first line of the input should contain a single integer t (1≤t≤10) — the number of test cases.
The first line of each test case should contain two integers n and k (2≤n≤1000,1≤k≤n) — the size of the array and the number of subsets. The next line should consist of n space separated integers in the range [1,n] — the array A. k lines should follow. The i-th line should contain an integer c (1≤c<n) — the size of subset Si, followed by c distinct integers in the range [1,n] — indices from the subset Si.
The intersection of any two subsets has to be empty.

这道题是一道通过子集实现,二分优化的题。要注意的是,这道交互题需要用到fflush。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(int x){
	if(x<2)return 0;
	for(int i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
int a[2000][2000],siz[2000],ans[2000];
int query(int x){
	cout<<"? "<<x; 
	for(int i=1;i<=x;i++){
		cout<<" "<<i;
	}
	cout<<endl;
	fflush(stdout);
	return read();
}
int main(){
	int T=read();
	while(T--){
		int n=read(),k=read();
		for(int i=1;i<=k;i++){
			siz[i]=read();
			for(int j=1;j<=siz[i];j++){
				a[i][j]=read();
			}
		}
		cout<<"? "<<n;
		for(int i=1;i<=n;i++){
			cout<<" "<<i;
		}
		cout<<endl;
		fflush(stdout);
		int MAX=read(),l=1,r=n,res=1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(query(mid)==MAX){
				r=mid-1;
				res=mid;
			}
			else l=mid+1;
		}
		int tmp=-1;
		memset(ans,0,sizeof(ans));
		for(int i=1;i<=k;i++){
			bool flag=false;
			for(int j=1;j<=siz[i];j++){
				if(a[i][j]==res){
					flag=true;
					tmp=i;
				}
			}
			if(!flag){
				ans[i]=MAX;
			}
		}
		if(tmp!=-1){
			map<int,int>hh;
			for(int j=1;j<=siz[tmp];j++){
				hh[a[tmp][j]]=1;
			}
			cout<<"? "<<n-siz[tmp]<<" ";
			for(int i=1;i<=n;i++){
				if(hh[i])continue;
				else cout<<i<<" ";
			}
			cout<<endl;
			fflush(stdout);
			ans[tmp]=read();
		}
		cout<<"! ";
		for(int i=1;i<=k;i++){
			cout<<ans[i];
		}
		cout<<endl;
		fflush(stdout); 
		string anss;
		scanf("%s",anss.c_str());
	}
	return 0;
}

E:Tree Shuffling

Ashish has a tree consisting of n nodes numbered 1 to n rooted at node 1. The i-th node in the tree has a cost ai, and binary digit bi is written in it. He wants to have binary digit ci written in the i-th node in the end.
To achieve this, he can perform the following operation any number of times:
Select any k nodes from the subtree of any node u and shuffle the digits in these nodes as he wishes, incurring a cost of k⋅au. Here, he can choose k ranging from 1 to the size of the subtree of uu.
He wants to perform the operations in such a way that every node finally has the digit corresponding to its target.
Help him find the minimum total cost he needs to spend so that after all the operations, every node u has digit cucu written in it, or determine that it is impossible.
Input
First line contains a single integer n (1≤n≤2⋅105) denoting the number of nodes in the tree.
i-th line of the next nn lines contains 3 space-separated integers ai, bi, ci (1≤ai≤109,0≤bi,ci≤1) — the cost of the i-th node, its initial digit and its goal digit.
Each of the next n−1 lines contain two integers u, v (1≤u,v≤n, u≠v), meaning that there is an edge between nodes u and v in the tree.
Output
Print the minimum total cost to make every node reach its target digit, and −1 if it is impossible.

这道题同时用到了dp和dfs。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(LL x){
	if(x<2)return 0;
	for(LL i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
inline LL read()
{
	LL x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
LL n=read(),ans;
LL a[300000],b[300000],c[300000],dp[300000][2];
vector<LL>dis[300000];
void dfs(LL x,LL fa){
	for(LL i=0;i<dis[x].size();i++){
		if(dis[x][i]!=fa){
			a[dis[x][i]]=min(a[dis[x][i]],a[x]);
			dfs(dis[x][i],x);
		}
	}
	return ;
}
void dpfs(LL x,LL fa){
	if(b[x]!=c[x])dp[x][b[x]]++;
	for(LL i=0;i<dis[x].size();i++){
		if(dis[x][i]!=fa){
			dpfs(dis[x][i],x);
			dp[x][1]+=dp[dis[x][i]][1];
			dp[x][0]+=dp[dis[x][i]][0];
		}
	}
	ans+=min(dp[x][1],dp[x][0])*a[x]*2;
	dp[x][1]-=min(dp[x][1],dp[x][0]),dp[x][0]-=min(dp[x][1],dp[x][0]);
	return ;
}
int main(){
	LL s1=0,s2=0;
	for(LL i=1;i<=n;i++){
		a[i]=read(),b[i]=read(),c[i]=read(),s1+=b[i],s2+=c[i];
	}
	if(s1!=s2){
		cout<<-1;
		return 0;
	}
	for(LL i=1;i<n;i++){
		LL u=read(),v=read();
		dis[u].push_back(v);
		dis[v].push_back(u);
	}
	dfs(1,0);
	dpfs(1,0);
	cout<<ans;
	return 0;
}

F:Rotating Substrings

You are given two strings s and t, each of length n and consisting of lowercase Latin alphabets. You want to make s equal to t.
You can perform the following operation on s any number of times to achieve it —
Choose any substring of s and rotate it clockwise once, that is, if the selected substring is s[l,l+1…r], then it becomes s[r,l,l+1…r−1]. All the remaining characters of s stay in their position.
For example, on rotating the substring [2,4] , string “abcde” becomes “adbce”.
A string a is a substring of a string b if aa can be obtained from bb by deletion of several (possibly, zero or all) characters from the beginning and several (possibly, zero or all) characters from the end.
Find the minimum number of operations required to convert s to t, or determine that it’s impossible.
Input
The first line of the input contains a single integer t (1≤t≤2000) — the number of test cases. The description of the test cases follows.
The first line of each test case contains a single integer n (1≤n≤2000) — the length of the strings.
The second and the third lines contain strings s and t respectively.
The sum of n over all the test cases does not exceed 2000.
Output
For each test case, output the minimum number of operations to convert s to t. If it is not possible to convert s to t, output −1 instead.

这道题用到了dp,相对复杂。

#include<bits/stdc++.h>
#define LL long long
#define U unsigned
bool isp(LL x){
	if(x<2)return 0;
	for(LL i=2;i<=sqrt(x);i++){
		if(x%i==0) return 0;
	}
	return 1;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
using namespace std;
int dp[3000][3000];
int main() {
	int T=read();
	while(T--){
		int n=read(),sn[3000][30],tn[3000][30];
		char s[3000],t[3000];
		scanf("%s%s",s+1,t+1);
		for(int i=1;i<=n;i++){
			for(int j=0;j<26;j++){
				sn[i][j]=sn[i-1][j];
				tn[i][j]=tn[i-1][j];
				if(s[i]-'a'==j){
					sn[i][j]++;
				}
				if(t[i]-'a'==j){
					tn[i][j]++;
				}
			}
		}
		bool flag=0;
		for(int j=0;j<26;j++){
			if(sn[n][j]!=tn[n][j]){
				flag=1;
			}
		}
		if(flag){
			cout<<-1;
		}else{
			memset(dp,0x7f7f7f7f,sizeof(dp));
			for(int i=0;i<=n;i++){
				dp[i][0]=dp[0][i]=0;
			}
			for(int i=1;i<=n;i++){
				for(int j=1;j<=n;j++){
					dp[i][j]=1+dp[i-1][j];
					if(s[i]==t[j]){
						dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
					}
					if(sn[i][t[j]-'a']<tn[j][t[j]-'a']){
						dp[i][j]=min(dp[i][j],dp[i][j-1]);
					}
				}
			}
			cout<<dp[n][n];
		}
		cout<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值