Manthan, Codefest 18 (rated, Div. 1 + Div. 2)

版权声明:版权所有,转载请标明 https://blog.csdn.net/zxwsbg/article/details/82350684

题目链接:http://codeforces.com/contest/1037

目录

A. Packets

题目

题解

代码

B. Reach Median

题目

题解

代码

C. Equalize

题目

题解

代码

D. Valid BFS

题目

题解

代码


A. Packets

题目

  拥有n个价值为1的硬币,要把它们分到若干个袋子里。要求使用若干个袋子的硬币和能凑出1-n的每个数,求要分的最小袋子数。举个例子,n=6,那么每个袋子里的硬币数分别为1,2,3;如果要凑4,就用1和3;要凑5,就用2和3;要凑6,就把它们全用了。

题解

  通过观察得到,如果有了1和2,那么就不需要3,因为它能被凑出来,但是需要4,因为它不能被凑出来。依此类推,有了4,就不需要5,6,7了,下一个需要的数字就是8。很容易看出来,我们的最优选法一定是1,2,4,8,16……这类。

  于是,给出一个n。答案就是log2(n)+1。因为1,2,4,8……求和的结果是 2^{n}-1 ,所以最终结果要+1。

代码

#include <bits/stdc++.h>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;

inline void read(int &x) {
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x) {
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

inline void caltime(int tt) {
	tt = clock() - tt;
    cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}

inline void print_matrix(int a[N][N],int n,int m,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}else {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}
}

inline void print_line(int *a,int n,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}else {
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
	}
	cout<<endl;
}

ll n,sum[maxn],ans;

int main()
{
	cin>>n;
	ans = log2(n);
	ans++;
	cout<<ans;
	return 0;
}


B. Reach Median

题目

  给出一个n(n为奇数)和s,然后输入n个数,现在可以将任意一个数+1或-1若干次。要求最小的操作次数,使得操作完后的数组经过排序后,其中位数恰好为s。

题解

  贪心(不会证)。

  首先将数组排序,然后将中位数和s比大小。如果比s大的话,那么就减小到s那么大,然后从当前位置向前遍历,遇到比它大的数都将它们变的和s一样大,然后统计出操作次数;如果比s小的情况同理。

代码

#include <bits/stdc++.h>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;

inline void read(int &x) {
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x) {
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

inline void caltime(int tt) {
	tt = clock() - tt;
    cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}

inline void print_matrix(int a[N][N],int n,int m,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}else {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}
}

inline void print_line(int *a,int n,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}else {
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
	}
	cout<<endl;
}

int n,s,a[maxn];

int main()
{
	cin>>n>>s;
	for(int i=0;i<n;i++) 
		read(a[i]);
	sort(a,a+n);
	ll ans = 0;
	int temp = a[n/2];
	if(s>temp) {
		ans += s-temp;
		for(int i=n/2+1;i<n;i++) {
			if(a[i]<s) {
				ans += s-a[i];
			}else {
				break;
			}
		}
	}else if(s<temp){
		ans += temp-s;
		for(int i=n/2-1;i>=0;i--) {
			if(a[i]>s) {
				ans += a[i]-s;
			}else {
				break;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}


C. Equalize

题目

  有两个01字符串a和b,现在可以对字符串a进行以下两种操作:

  (1)将位置i和位置j互换,这样的花费为 |j-i| ;

  (2)将位置i改变。 (即0变成1,1变成0)

       问如果要让a和b相等,需要的最小代价是多少。

题解

  首先我们来看操作1,如果把任何两个距离大于1的位置互换,那么代价一定大于1,也就是不小于操作2的代价。

       于是,我们只对距离为1的进行操作1,其余均进行操作2,然后就剩下一些代码细节了。

代码

#include <bits/stdc++.h>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;

inline void read(int &x) {
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x) {
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

inline void caltime(int tt) {
	tt = clock() - tt;
    cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}

inline void print_matrix(int a[N][N],int n,int m,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}else {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}
}

inline void print_line(int *a,int n,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}else {
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
	}
	cout<<endl;
}

int n;
string a,b;

int main()
{
	cin>>n>>a>>b;
	int res = 0;
	for(int i=0;i<n;) {
		if(a[i]!=b[i]) {
			res++;
			if(i<n-1&&a[i+1]!=a[i]&&a[i+1]!=b[i+1]) {
				i++;
			}
		}
		i++;
	}
	cout<<res<<endl;
	return 0;
}


D. Valid BFS

题目

  给一棵树,然后再给一个序列。问该序列是否是这棵树合法的BFS序。

题解

  由于给定的bfs序对于同一父节点,其子节点的遍历顺序是无序的,但是大的顺序不会改变。

  所以可以根据给定的顺序来对每一个父节点排序,这样能保证子节点的顺序和给出的顺序一致。

  最后进行BFS,看与给定序列是否相同即可。

代码

#include <bits/stdc++.h>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
#define next next_
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
const int N = 105;

inline void read(int &x) {
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x) {
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

inline void caltime(int tt) {
	tt = clock() - tt;
    cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}

inline void print_matrix(int a[N][N],int n,int m,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}else {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++)
				cout<<a[i][j]<<" ";
			cout<<endl;
		}
	}
}

inline void print_line(int *a,int n,bool flag=0) {
	if(flag) {
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}else {
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
	}
	cout<<endl;
}

int n,a[maxn];
int reorder[maxn];
bool vis[maxn];
vector<int> e[maxn];
vector<int> s;
int height = -1;

bool cmp(int a,int b) {
	return reorder[a]<reorder[b];	
}

void bfs() {
	queue<int> q;
	q.push(1);
	while(!q.empty()) {
		int res = q.front();
		q.pop();
		s.push_back(res);
		vis[res] = 1;
		for(int i=0;i<e[res].size();i++) {
			if(!vis[e[res][i]])
				q.push(e[res][i]);
		}
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n-1;i++) {
		int x,y;
		read(x),read(y);
		e[x].push_back(y); //不能保证一定是由父亲指向儿子,所以添加两次
		e[y].push_back(x);
	}
	for(int i=0;i<n;i++) {
		read(a[i]);
		reorder[a[i]] = i;
	}
//	print_line(reorder,n);
	for(int i=1;i<=n;i++) {
		sort(e[i].begin(),e[i].end(),cmp);
	}
	bfs();
	bool flag = 1;
	for(int i=0;i<n;i++) {
		if(s[i]!=a[i]) {
			flag = 0;
			break;
		}
	}
	if(flag)	cout<<"Yes"<<endl;
	else	cout<<"No"<<endl;
	return 0;
}


猜你喜欢

转载自blog.csdn.net/zxwsbg/article/details/82350684