Codeforces Round #658 (Div. 1) A1~C题解,Codeforces Round #658 (Div. 2) C1~E题解

A1,A2 - Prefix Flip

首先可以发现由a变到0,需要最多n次,方法如下:
对于第i位(i<a.length()-1),如果a[i] != a[i+1],对于a[0]到a[i]执行操作。
然后b到0,也最多n次。把a到0的操作+0到b的操作就是答案。

/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
vector<int> work(string s){
	vector<int> res;
	rep(i,s.length()){
		if(i!=s.length()-1&&s[i]!=s[i+1]){
			res.PB(i+1);
		} 
	}
	if(s[s.length()-1]=='0'){
		
	}
	else{
		res.PB(s.length());
	}
	return res;
}
void solve(){
	int  n;
	cin>>n;
	string s1,s2;
	cin>>s1>>s2;
	vector<int> res,res2;
	res=work(s1);
	res2=work(s2);
	reverse(ALL(res2));
	cout<<res.size()+res2.size()<<" ";
	for(auto it:res) cout<<it<<" ";for(auto it:res2) cout<<it<<" ";cout<<endl;
}
int main(){
	fastio;
	int t;
	cin>>t;
	while(t--) solve();
	
	return 0;
}

B - Unmerge

可以发现merge操作时在一个空串中连续加入几个段 [ l 1 , r 1 ] , [ l 2 , r 2 ] , [ l 3 , r 3 ] . . . [ l k , r k ] [l_1,r_1],[l_2,r_2],[l_3,r_3]...[l_k,r_k] [l1,r1],[l2,r2],[l3,r3]...[lk,rk]其中 [ l i , r i ] [l_i,r_i] [li,ri]来自a那么( i M O D 2 = = 1 iMOD2==1 iMOD2==1),否则来自b。
然后由于第一段走完了第二段才走,所以 a l 2 > m a x { a l 1 . . . r 1 } a_{l_2}>max\{a_{l_1...r_1}\} al2>max{al1...r1},同理 a l 3 > m a x { a l 2 . . . r 2 } ⇒ a l 3 > a l 2 > m a x { a 1 . . . a r 2 } a_{l_3}>max\{a_{l_2...r_2}\} \Rightarrow a_{l_3}>a_{l_2}>max\{a_1...a_{r_2}\} al3>max{al2...r2}al3>al2>max{a1...ar2}
所以 l i l_i li必须满足 a l i a_{l_i} ali a 1 . . . a l i − 1 a_1...a_{l_i-1} a1...ali1中最大的一个,这样我们就可以发现 l i l_i li的可能位置。然后就有了这些段。
d p i , j dp_{i,j} dpi,j表示考虑前i个段总长度=j,是否可能。
d p i , j = d p i − 1 , j ∣ d p i − 1 , j − l i dp_{i,j}=dp_{i-1,j}|dp_{i-1,j-l_i} dpi,j=dpi1,jdpi1,jli

/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
bool dp[4004][2002];
int a[4004];
void solve(){
	memset(dp,0,sizeof(dp));
	int n;
	cin>>n;
	n<<=1;
	rb(i,1,n){
		cin>>a[i];
	}
	vector<int> v;
	dp[0][0]=1;
	int st=1;
	int maxi=a[1];
	rb(i,2,n){
		if(a[i]>maxi){
			v.PB(i-st);
			st=i;
		} 
		maxi=max(a[i],maxi);
	}
	v.PB(n-st+1);
	rb(i,1,v.size()){
		rb(j,0,n/2){
			dp[i][j]|=(j>=v[i-1]? dp[i-1][j-v[i-1]]:0)|dp[i-1][j];
		}
	}
	if(dp[v.size()][n/2]){
		cout<<"YES"<<endl;
	}
	else{
		cout<<"NO"<<endl;
	}
}
int main(){
	fastio;
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

C - Mastermind

定义 p i c k = y − x pick=y-x pick=yx,显然就是要从数组中取出 p i c k pick pick个数交换位置,使得每一个位置的数与原来不同,其余的选n-y个把颜色换成没出现的颜色。特殊的: p i c k = m i n ( 2 , n − x ) pick=min(2,n-x) pick=min(2,nx);如果只有两种颜色, p i c k pick pick为最小的偶数大于等于 y − x y-x yx的偶数。
假设选出来的数位 { a 1 . . . a p i c k } \{a_1...a_{pick}\} {a1...apick},显然如果最多的数 > ⌊ n 2 ⌋ >\lfloor \frac{n}{2} \rfloor >2n则肯定不满足。否则将a数组按照个数的多少降序排序(相同的数排在一起),将第一种颜色的第一个连向第二种颜色的第一个,第一种颜色的第二个连向第二种颜色的第二个…
code:

/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;

int n,x,y;
int cnt[100000+20],al[100000+20],a[100000+20],res[100000+20];
bool cmp(int A,int B){
	if(al[a[A]]!=al[a[B]])
	return al[a[A]]>al[a[B]];
	return a[A]<a[B];
}
int find_(int l,int r){
	if(l==1) l++;
	int kk=0;
	rb(i,1,n+1){
		if(cnt[i]){
			kk++;
		}
	}
	if(kk==2){
		if(l&1){
			l++;
		}	
	}
	return min(r,l);
}
void solve(){
	get(n);
	get2(x,y);
	memset(cnt,0,sizeof(cnt));
	memset(al,0,sizeof(al));
	memset(res,0,sizeof(res));
	rb(i,1,n){
		get(a[i]);
		cnt[a[i]]++;
	}
	int pick=y-x;
	vector<int> pos;
	int ok=0;
	int f=find_(pick,n-x);
	ok=f-pick;
	pick=f;
	rb(i,1,n){
		if((al[a[i]]+1)*2>pick||pos.size()==pick){
			if(x){
				x--;
				res[i]=a[i];
			}
		}
		else{
			al[a[i]]++;
			pos.PB(i);
		}
	}
	if(pos.size()<pick){
		cout<<"NO"<<endl;
		return ;
	}
	cout<<"YES"<<endl;
	sort(ALL(pos),cmp);
	int zhi;
	rep(i,pos.size()){
		if(a[pos[i]]!=a[pos[0]]){
			zhi=i;
			break;
		}
	}
	rep(i,pos.size()){
		res[pos[zhi]]=a[pos[i]];
		zhi++;
		zhi%=pos.size();
	}
	int tmp;
	rb(i,1,n+1){
		if(!cnt[i]) tmp=i;
	}
	rb(i,1,n){
		if(!res[i])
			res[i]=tmp;
		else
		if(ok&&res[i]!=a[i]){
			ok--;
			res[i]=tmp;
		}
	}
	rb(i,1,n) cout<<res[i]<<" ";cout<<endl;
}
int main(){
	fastio;
	int t;
	cin>>t;
	while(t--) solve();
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值