(CodeForces) Round #550 (Div. 3) (全)

传送门

A. Diverse Strings

解题思路:先对字符串排序然后判断一下就行了。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d%d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
bool pd(string s) {
	sort(s.begin(),s.end());
	for (int i=1;i<sz(s);++i) 	if (s[i]!=s[i-1]+1) return false;
	return true;
}
int n;
int main(){
	cin>>n;
	rep(i,1,n) {
		string s;
		cin>>s;
		cout<<(pd(s)? "Yes\n" : "No\n");
	}
}

B. Parity Alternated Deletions

解题思路:如果奇数个数和偶数个数相差不超过1,那就是可以取完的,反之我们去不掉的,那就剩下小的就好了。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d%d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
vector<int> even,odd;
int n,tp;
int main() {
	std::ios::sync_with_stdio(0);
	cin>>n;
	rep(i,1,n) {
		cin>>tp;
		if(tp&1)	odd.pb(tp);
		else even.pb(tp);
	}
	if(abs(sz(odd)-sz(even))<=1)	cout<<0<<endl;
	else {
		ll sum=0;
		sort(odd.begin(),odd.end());
		sort(even.begin(),even.end());
		if(sz(odd)>sz(even))	rep(i,0,sz(odd)-sz(even)-2)	sum+=odd[i];
		else	rep(i,0,sz(even)-sz(odd)-2)	sum+=even[i];
		cout<<sum<<endl;
	}
	return 0;
}

C. Two Shuffled Sequences

解题思路:一个元素个数超过3个那肯定不能分成两个满足条件的序列,如果两个一样的元素那就每个序列放一个,反之放哪个都是一样的,最后排个序就行了。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d%d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+5;
int n,tp;
bool f1,f2;
map<int,int> num; 
vector<int> de,inde;
int main(){
	std::ios::sync_with_stdio(0);
	cin>>n;
	rep(i,1,n){
		cin>>tp;
		if(++num[tp]>=3)	f1=1;
		if(num[tp]==2)	f2=1;
	} 
	if(f1)	cout<<"NO"<<endl;
	else if(!f2){
		cout<<"YES"<<endl<<num.size()<<endl;
		for(auto it=num.begin();it!=num.end();++it)	cout<<it->fi<<" ";
		cout<<endl<<0<<endl;
	}
	else{
		for(auto it=num.begin();it!=num.end();++it){
			if(it->se==2)	de.pb(it->fi),inde.pb(it->fi);
			else	de.pb(it->fi);
		}
		sort(de.begin(),de.end());
		sort(inde.begin(),inde.end(),greater<int>() );
		cout<<"YES"<<endl<<de.size()<<endl;
		rep(i,0,sz(de)-1)	cout<<de[i]<<" ";
		cout<<endl<<inde.size()<<endl;
		rep(i,0,sz(inde)-1)	cout<<inde[i]<<" ";
	}
	return 0;
}

D. Equalize Them All

解题思路:让所有的数字变成那个出现频率最高的数无疑是步数最少的,题干中的那步操作,其实就是使两个数字相同,大了那就减去差,小了那就加上差,所有只要从出现频率最高的那个数字开始往两边走就行了,大了就2操作,小了就1操作。(不需要像代码还找个区间,写烦了)

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+5;
int n,a[maxn],le=1,ri=1,num,id;
int co[maxn];
struct node{
	int x,i,j;
}ans[maxn];
int main(){
	std::ios::sync_with_stdio(0);
	cin>>n;
	rep(i,1,n){
		cin>>a[i];
		co[a[i]]++;
		if(co[a[i]]>num){
			num=co[a[i]];
			id=a[i];
		}
	}	
	for(int i=1;i<=n;++i){
		if(a[i]==id){
			int j;
			for(j=i;j<=n;++j)	if(a[j]!=id)	break;
			le=i,ri=j-1;
			break;
		}
	}
	int cnt=0;
	for(int i=le-1;i>=1;--i){
		if(a[i]>id)	ans[++cnt]=node{2,i,i+1};
		else if(a[i]<id)	ans[++cnt]=node{1,i,i+1};
	}
	for(int i=ri+1;i<=n;++i){
		if(a[i]>id) ans[++cnt]=node{2,i,i-1};
		else if(a[i]<id)	ans[++cnt]=node{1,i,i-1};
	}
	cout<<cnt<<endl;
	rep(i,1,cnt)	cout<<ans[i].x<<" "<<ans[i].i<<" "<<ans[i].j<<endl;
	
	return 0;
}

E. Median String

解题思路:如果给我们两个数求他们中间的那个数,我们都会求,加起来除2就行了,我们可以把字符串看成26进制不就行了嘛。模拟26进制计算,最后在转化回字符串就行了。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+7;
int n,sum[maxn];
string a,b;
map<int,int> mp;
int main(){
	std::ios::sync_with_stdio(0);
	cin>>n>>a>>b;
	int i=0;
	for(char x='a';x<='z';++x){
		mp[x]=i,mp[i]=x,++i;
	}
	int cur=0,tp,cnt=0;
	for(int i=sz(a)-1;i>=0;--i){
		tp=mp[a[i]]+mp[b[i]]+cur;
		sum[cnt]=tp%26;
		cur=tp/26;
		cnt++;
	}
	if(cur)	sum[cnt]=cur;
	else	cnt--;
	for(int i=cnt;i>=0;--i){
		if(sum[i]&1)	sum[i-1]+=26;
		sum[i]/=2;
	}
	if(cnt>n-1)	cnt--;
	for(int i=cnt;i>=0;--i)	cout<<char(mp[sum[i]]);
	return 0;
}

F. Graph Without Long Directed Paths

解题思路:分析题意,不能有>=2的路径,其实就是每个点的边,要不就是全部指向它,要不然就是全部从它出去。这样就不会有>=2的路径出现了。然后我们用搜索就可以解决这个问题,我写的比较啰嗦.....丧。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+7;
bool ans[maxn],vis[maxn];
struct edge{
	int id,x,y;
	bool fg;
};
vector<edge> mp[maxn];
bool pd=0;
int n,m;
void solve(int np,bool fg){ //当前点,fg=0代表所有的边都是出边,反之入边
	rep(i,0,sz(mp[np])-1){
		edge tp=mp[np][i];
		if(pd)	return;
		if(!vis[tp.id]){
			vis[tp.id]=1;
			if(tp.x==np && fg==1)	ans[tp.id]=0;
			else if(tp.x==np && fg==0)	ans[tp.id]=1;
			else if(tp.x!=np && fg==1)	ans[tp.id]=1;
			else if(tp.x!=np && fg==0)	ans[tp.id]=0;
			if(tp.x!=np)  solve(tp.x,fg^1);
			else solve(tp.y,fg^1);
		}
		else{
			if(fg==1 && tp.x==np && ans[tp.id]==1){
				pd=1;return;
			}	
			else if(fg==1 && tp.x!=np && ans[tp.id]==0){
				pd=1;return;
			}	
			else if(fg==0 && tp.x==np && ans[tp.id]==0){
				pd=1;return;
			}	
			else if(fg==0 && tp.x!=np && ans[tp.id]==1){
				pd=1;return;
			}	
		}
	} 
}
int main(){
	std::ios::sync_with_stdio(0);
	cin>>n>>m;
	int x,y;
	rep(i,1,m){
		cin>>x>>y;
		mp[x].pb(edge{i,x,y,0});
		mp[y].pb(edge{i,x,y,0});
	}
	solve(1,0);
	if(pd)	cout<<"NO"<<endl;
	else{
		cout<<"YES"<<endl;
		rep(i,1,m)	cout<<ans[i];
	}
	return 0;
}

G. Two Merged Sequences

解题思路:对于一个数如果它只能放两个队列之一,那我就将其放入,如果两个都不能,那这个数列构造肯定就失败了。

如果它两个队列都能放入呢,那我们就看它的下一个元素,会有三种情况,1.相同,那就每个队列塞一个。2.下一个元素比它大,那就把他放到递增序列。3.下一个元素比它小,那就把它放到递减序列。这样考虑其实对当前元素不作选择了,因为我们这样放,它不影响下一个元素选择摆放。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+5;
int n,a[maxn];
bool ans[maxn];
priority_queue<int,vector<int>,greater<int> > inde; //下降
priority_queue<int> de; //上升序列
int main() {
	std::ios::sync_with_stdio(0);
	cin>>n;
	rep(i,1,n)	cin>>a[i];
	if(n==1){
		cout<<"YES"<<endl<<1<<endl;
		return 0;
	}
	de.push(-inf),inde.push(inf);
	int i=1;
	if(a[i+1]>a[i])	de.push(a[i]),ans[i]=0;
	else if(a[i+1]<a[i])	inde.push(a[i]),ans[i]=1;
	else de.push(a[i]),inde.push(a[++i]),ans[i-1]=0,ans[i]=1;
	++i;
	while(i<=n) {
		if(a[i]>de.top() && a[i]<inde.top()) {
			if(a[i+1]>a[i])	de.push(a[i]),ans[i]=0;
			else if(a[i+1]<a[i])	inde.push(a[i]),ans[i]=1;
			else de.push(a[i]),inde.push(a[++i]),ans[i-1]=0,ans[i]=1;
		} 
		else if(a[i]>de.top())	de.push(a[i]),ans[i]=0;
		else if(a[i]<inde.top())	inde.push(a[i]),ans[i]=1;
		else {
			cout<<"NO"<<endl;
			return 0;
		}
		++i;
	}
	cout<<"YES"<<endl;
	rep(i,1,n)	cout<<ans[i]<<" ";
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值