Codeforces Round #550 (Div. 3)

D:

给两种操作,问最少需要多少次操作可以使得数组所有数字相等。

找出出现次数最多的数字x,以他为基准向左向右扫一遍数组,找x!=y,如果y<x,则给y执行操作一,否则操作二。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
map<int,int>m;
const int maxn=2e5+7;
struct Node{
	int id;
	int w;
	int ci;
	bool operator <(const Node& x)const{
		return ci>x.ci;
	}
}b[maxn];

int a[maxn];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		b[a[i]].id=i;
		b[a[i]].w=a[i];
		++b[a[i]].ci;
	}
	sort(b,b+maxn);
	int x=n-b[0].ci;
	printf("%d\n",x);
	if(!x) return 0;
	int id=b[0].id;
	int w=b[0].w;
	for(int i=id-1;i>=1;--i){
		if(a[i]>w)
			printf("%d %d %d\n",2,i,id);
		else if(a[i]<w)
			printf("%d %d %d\n",1,i,id);
		id=i;
	}
	id=b[0].id;
	for(int i=id+1;i<=n;++i){
		if(a[i]>w)
			printf("%d %d %d\n",2,i,id);
		else if(a[i]<w)
			printf("%d %d %d\n",1,i,id);
		id=i;
	}
	return 0;
}

 

E:

给两个长度为k的字符串s,t,并且字典序s<t,而且字典序在s与t之间的字符串有奇数个,在奇数个字符串组成的序列中寻找中间串,并输出。

首先我们考虑两个十进制数字的中间值怎么找,a和b,中间值为:(a+b)/2,那么字符串也是同理,是二十六进制下的寻找中间值,模拟二十六进制加法,再计算其除以2的值,即为结果串。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
using namespace std;

const int maxn=2e5+7;

char s[maxn],t[maxn];
string h;

int a[maxn];//每一位的二十六进制数; 

int main(){
	int k;
	cin>>k>>s>>t;
	h="";
	int res=0;
	int jin=0;//进位; 
	
	int j=0;
	for(int i=k-1;i>=0;--i){
		int yu=(s[i]-'a'+t[i]-'a'+jin)%26;
		a[j++]=yu;
		jin=(s[i]-'a'+t[i]-'a'+jin)/26;
	}
	int x=0;
	if(jin) a[j++]=jin;
	for(int i=j-1;i>=0;--i){
		x=x*26+a[i];
		//比如两个串长度为k 由于产生进位出现长度为k+1,那么最高位我们是不要的。 
		if(i>=k){
			x%=2;
			continue;
		}
		h+='a'+(x/2);
		x%=2;
	}
	cout<<h<<endl;
	
	
	return 0;
}

E:给出一个无自环,无重边,无向连通图,问能否将该无向图转换为有向图,使得每条路径长度都为1。

图着色,将每个点着色,如果可行,说明可以转化为有向图,白->黑为正向边,黑->白为反向边,输出的时候,由于使用邻接表存图,那么正向边下标为偶数,反向边为奇数,且正向边^1=反向边的下标。

 

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;

const int maxn=2e5+7;

int head[maxn];
int top;
void init(){
	top=0;
	memset(head,-1,sizeof(head));
}

struct Edge{
	int v,next;
}edge[maxn<<1];

void add(int u,int v){
	edge[top].v=v;
	edge[top].next=head[u];
	head[u]=top++;
}

int color[maxn];

bool dfs(int u,int f){
	color[u]=f;
	bool flag=true;
	for(int i=head[u];i!=-1;i=edge[i].next){
		int v=edge[i].v;
		if(color[v]==color[u]) return 0;
		if(color[v]==-1){
			flag=flag&dfs(v,f^1);
		}
	}
	return flag;
} 

int a[maxn];
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	init();
	int u,v;
	for(int i=0;i<m;++i){
		scanf("%d%d",&u,&v);
		//++mm[make_pair(u,v)];
		add(u,v);
		add(v,u);
	}
	memset(color,-1,sizeof(color));
	if(dfs(1,0)){
		printf("YES\n");
		for(int i=0;i<m;++i){
			int id=i*2;
			if(color[edge[id].v]==0) printf("1");
			else printf("0");
		}
		printf("\n");
	}
	else
		printf("NO\n");
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值