其他分享
首页 > 其他分享> > Codeforces Round #787 (Div. 3) 解题报告

Codeforces Round #787 (Div. 3) 解题报告

作者:互联网

A. Food for Animals

题意:商店有a个狗粮,b个猫粮 ,c个通用粮,需要x个狗粮,y个猫粮,问是否能满足需要
判断猫和狗能否都被满足即可
ac代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int main()
{
	ios;
	
	int t;
	cin >> t;
	while(t --)
	{
		int a,b,c,x,y;
		cin >> a >> b >> c >> x >> y;
		
		if(a >= x) ;
		else  c -= x - a;
		if(c < 0 ) 
		{
			cout << "NO" << endl;
			continue;
		}
		if(b + c >= y) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

B. Make It Increasing

题意:给定一个数列a,定义操作:对任意一个a[i] / 2(向下取整),问能够将这个数列构造成严格递增数列的最小操作数。
从后往前搜一遍,只要a[i] >= a[i + 1] 就进行一次操作。最后判断一下是否严格递增。
注意:如果a[i] < 0 ,操作会使其变大。
ac代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,a[N];

int main()
{
	ios;
	
	int t;
	cin >> t;
	while(t --)
	{
		cin >> n;
		for(int i = 0;i < n;i ++) cin >> a[i];
		bool f = true;
		LL res = 0;
		for(int i = n - 2;i >= 0;i --)
		{
			while(a[i] && a[i] >= a[i + 1])
			{
				res ++;
				a[i] /= 2;
			}
		}
		for(int i = 1;i < n;i ++) if(a[i] <= a[i - 1]) f = false;
		if(f) cout << res << endl;
		else cout << -1 << endl;
	}
	return 0;
}

C. Detective Task

题意:n个人依次进房间看画,有一个人偷了画,按看画次序问,结果为(1:还在,0:不在, ?:不记得),除小偷外其他人都说的实话,问嫌疑人个数。
如果一个人是小偷,那么其他人说的都是实话,那么他前面的人肯定是没有人说不在的,后面的人肯定没有说还在的
即对于一个可能的点其前面没有0,后面没有1,所以只要找到第一个出现的0的位置r,再找到其第一个为1的位置l,则中间的全是嫌疑人,ans = r - l + 1;

ac代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,a[N],b[N];


int main()
{
	ios;
	
	int t;
	cin >> t;
	while(t --)
	{
		string s;
		cin >> s;
		int l,r;
		for(r = 0;r < s.size() - 1;r ++)
		{
			if(s[r] == '0') break;
		}
		for(l = r;l;l --)
		{
			if(s[l] == '1') break;
		}

		cout << r - l + 1 << endl;
	}
	return 0;
}

D. Vertical Paths

题意:给定一颗树,问把这颗树拆成几条路径的最小值,并输出路径
dfs回溯过程中如果接着往深处走,就是一条新路径

ac代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,p[N];
int h[N],e[N],ne[N],idx,idxx;

void add(int a,int b)
{
	e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}

map<int,int> mp;
int path[N];
bool st[N];
vector<int > a[ N ];
void dfs(int u,int c)
{
	path[c] = u;
	if(h[u] == -1)
	{
		a[idxx].clear();
		for(int i = 0;i <= c;i ++) a[idxx].push_back(path[i]);
		idxx ++;
		c = -1;
		return ;
	}
	for(int i = h[u];i != -1;i = ne[i])
	{
		int j = e[i];
		dfs(j,c + 1);
	}
}

int main()
{
	ios;
	
	int t;
	cin >> t;
	while(t --)
	{

		int tt;
		idx = idxx = 0;
		mp.clear();
		cin >> n;
		memset(h,-1,(n + 1) * 4);
		for(int i = 1;i <= n;i ++)
		{
			int x;
			cin >> x;
			mp[x] = 1;
			if(x == i)
			{
				tt = i;
				continue;
			}
			add(x,i);
		}

		dfs(tt,0);
		memset(st,0,sizeof st);
		cout << idxx << endl;
		for(int i = 0;i < idxx;i ++)
		{
			int pos;
			for(pos = 0;pos < a[i].size();pos ++) if(!st[a[i][pos]]) break;
			cout << a[i].size() - pos << endl;
			for(;pos < a[i].size(); pos ++) cout << a[i][pos] <<  ' ',st[a[i][pos]] = true;
			cout << endl;
		}
		cout << endl;
	}
	return 0;
}

E. Replace With the Previous, Minimize

题意:给定一个字符串,定义操作:

if(s[i] == 'a') s[i] = 'z';
else s[i] -= 1;

并且整个字符串中与s[i]相同的字符,都会一起变化,问用k个操作所能得到的字典序最小字符串。
大体思路即尽量让前面的字母变成'a',变不了就尽量往小减。
同时注意到如果一个字符可以变成'a',并且前面的字母都比他小,那么只需对它操作就可以让前面全变为'a'。
不难想到字符串是这样的

红色的结尾是那个第一个不能变成'a'的字符,其前面的只需找到最大的那个对其操作即可。
ac代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

map<char,char> mp;
bool st[N];
int main()
{
	ios;
	int t;
	cin >> t;
	while(t --)
	{
		int n,k;
		string s;
		cin >> n >> k >> s;
		for(char i = 'a';i <= 'z';i ++) mp[i] = i;
		
		int res = 0;
		for(int i = 0;i < n;i ++)
		{
			if(s[i] - 'a'> k)
			{
				char l = s[i] - k + res;
				char r = s[i];
				if(l > r) break;
				for(int j = 0;j < n;j ++)
				{
					if(s[j] >= l && s[j] <= r)
					{
						s[j] = l;
					}
				}
				break;
			}
			res = max(res,s[i] - 'a');
		}
		for(int j = 0;j < n;j ++) if(s[j] <=  'a' + res) s[j] = 'a';
		cout << s << endl;

	}
	return 0;
}

F. Vlad and Unfinished Business

题意:给定一颗无根树,以及起点x,终点y。从起点要先经过一系列点然后最终到y,问最短距离。
bfs标记每个节点的父节点并计算距起点的最短距离。
如果想要在一个树上,要求从根出发,经过若干个点的话,最后回到根,基本想法就是从要经过的点往根遍历,没经过一条边,就要代价 +2,因为一次是往下,第二次是经过了该子树要经过的点,然后回去
所以这题就套用这个想法,把 y 也作为要经过的点,然后再减去 x 到 y 的距离,就变成最后是在 y 点停下

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
//#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int h[N], e[N * 2], ne[N * 2], idx;
int p[N],d[N];
int n,k,x,y;
void add(int a,int b)
{
	e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}

void bfs(int s)
{
	//memset(d,-1,sizeof (int) * (n + 4) ) ;
	memset(p,-1,sizeof (int) * (n + 4));
	p[s] = 0;
	
	queue<PII> q;
	q.push((PII){s,0});
	while(q.size())
	{
		auto t = q.front();
		q.pop();
		int u = t.x;
		d[t.x] = t.y;
		for(int i = h[u];i != -1;i = ne[i])
		{
			int j = e[i];
			if(p[j] == -1)
			{
				p[j] = u;
				q.push({j,d[t.x] + 1});
			}
		}
	}
}
int a[N];
bool st[N];
int main()
{
	ios;
	int t;
	cin >> t;
	while(t --)
	{
		
		cin >> n >> k;
		cin >> x >> y;
		memset(h,-1,sizeof (int) * (n + 4));
		memset(st,0,sizeof (bool) * (n + 4));
		idx = 0;
		
		for(int i = 0;i < k;i ++) cin >> a[i];

		for(int i = 0;i < n - 1;i ++) 
		{
			int a,b;
			cin >> a >> b;
			add(a,b),add(b,a);
		}

		bfs(x);
		
		int res = 0;
		a[k ++] = y;
		st[x] = true;
		for(int i = 0;i < k;i ++)
		{
			int t = a[i];
			while(!st[t])
			{
				st[t] = true;
				t = p[t];
				res += 2;
			}
		}
		
		cout << res - d[y]<< endl;
	}
	return 0;
}

标签:typedef,787,int,ios,Codeforces,cin,Div,include,define
来源: https://www.cnblogs.com/notyour-young/p/16228362.html