第七天打卡 Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)

A题:找出有多少个每一个位置上数字都相同的数。
模拟即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t, n;
int pos[100];
int main()
{
	t = read();
	while (t--)
	{
		n = read();
		int nums = 0;
		int tempn = n;
		while (tempn)
		{
			pos[++nums] = tempn % 10;
			tempn /= 10;
		}
		int tempnum = nums;
		int sum = 0;
		while (tempnum)
		{
			sum *= 10;
			sum++;
			tempnum--;
		}
		sum *= pos[nums];
		int ans = 0;
		ans += 9 * (nums - 1);
		ans += n >= sum ? (pos[nums]) : (pos[nums] - 1);
		printf("%d\n", ans);
	}
	return 0;
}

B题
题意:每一次可以使得相等的数字除以二,问最少次操作使得数组全部变成奇数。
暴力模拟,开一个set,每一次贪心用最大的来除以2,再暴力合并进入set。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t, n;
const int N = 2e5 + 10;
int a[N];
set<int>s;
int main() {
	t = read();
	while (t--) {
		n = read();
		upd(i, 1, n)
		{
			a[i] = read();
			if (a[i] % 2 == 0)
			{
				s.insert(a[i]);
			}
		}
		int ans = 0;
		while (!s.empty())
		{
			int top = *(--s.end());
			if (top % 2)s.erase(*(--s.end()));
			else
			{
				s.erase(*(--s.end()));
				ans++;
				top /= 2;
				s.insert(top);
			}
		}
		cout << ans << endl;
	}
}

c题
题意:给一个字符串,问不能有one和two,每一次操作删掉一个字符,问最小操作。
可以发现,one和two最多公用一个o,也就是重叠出 twone这种情况。我们特判这种情况,删掉o相当于去除两个不正确的字符串。其他分别判断two和one即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t, n;
const int N = 2e5 + 10;
char s[N];
int pos[N];
int main()
{
	t = read();
	while (t--)
	{
		scanf("%s", s + 1);
		n = strlen(s + 1);
		upd(i, 1, n)pos[i] = 0;
		string ss;
		upd(i, 1, n-2) {
			ss = "";
			upd(j, i, i + 2)
			{
				ss += s[j];
			}
			if (ss == "two")pos[i] = 2;
			if (ss == "one")pos[i] = 1;
		}
		int ans = 0;
		vector<int>vec;
		upd(i, 1, n)
		{
			if (pos[i])
			{
				if (pos[i] == 1)
				{
					if (i > 2 && pos[i - 2] == 2)
					{
						vec.pop_back();
						vec.push_back(i);
						continue;
					}
					else
					{
						ans++;
						if (i > 1)
						{
							if (s[i-1] == 'o')vec.push_back(i + 1);
							else vec.push_back(i);
						}
						else 
						vec.push_back(i);
					}
				}
				else
				{
					if (i > 1)
					{
						if (s[i - 1] == 't')vec.push_back(i + 1);
						else vec.push_back(i);
					}
					else vec.push_back(i);
					ans++;
				}
			}
		}
		printf("%d\n", ans);
		for (auto k : vec)
		{
			printf("%d ", k);
		}
		cout << endl;
	}
	return 0;
}

D题
题意:给出n个01字符串,要求首尾相连,不能有重复字符串。每一次操作可以使得一个字符串反转,求最小操作次数。
考虑收尾两个字符,我们将字符串缩小成为两个字符。
我们可以发现,01,10之间,可以加入n个11字符串,然后又可以再末尾加入n个00.所以错误情况有,同时又11和00且没有任何10和01。
继续判断10和01的关系,10和01必须保持差1或者相等才能完全匹配。
我们暴力模拟该过程即可。b

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t, n;
const int N = 2e5 + 10;
string s[N];
map<string, int>mp;
vector<int>vec[5];
int lf[N], rt[N];
vector<int>ans;
int main()
{
	t = read();
	while (t--)
	{
		n = read();
		up(i, 0, 4)vec[i].clear(); mp.clear(); ans.clear();
		upd(i, 1, n)
		{
			cin >> s[i];
			mp[s[i]] = 1;
			if (s[i].front() == '0' && s[i].back() == '1')vec[1].push_back(i);
			if (s[i].front() == '1' && s[i].back()== '0')vec[2].push_back(i);
			if (s[i].front() == '0' && s[i].back() == '0')vec[0].push_back(i);
			if (s[i].front() == '1'&&s[i].back() == '1')vec[3].push_back(i);
		}
		if (vec[3].size() && vec[0].size() && vec[1].size() == 0 && vec[2].size() == 0) { printf("%d\n", -1); continue; }
		int x = vec[1].size();
		int y = vec[2].size();
		string temps="";
		if (x > y)
		{
			int cnt = 0;
			while (y + 1 < x&&cnt<vec[1].size())
			{
				int v = vec[1][cnt];
				temps = s[v];
				reverse(temps.begin(), temps.end());
				if (mp[temps])
				{
					cnt++;
					continue;
				}
				else
				{
					ans.push_back(v);
					y++; x--; cnt++;
				}
			}
			if (abs(y - x) <= 1)
			{
				printf("%d\n", ans.size());
				for (auto k : ans)
				{
					printf("%d ", k);
				}
				cout << endl;
			}
			else
			{
				printf("%d\n", -1);
				continue;
			}
		}
		else
		{
			int cnt = 0;
			while (x + 1 < y&&cnt < vec[2].size())
			{
				int v = vec[2][cnt];
				temps = s[v];
				reverse(temps.begin(), temps.end());
				if (mp[temps])
				{
					cnt++;
					continue;
				}
				else
				{
					ans.push_back(v);
					x++; y--; cnt++;
				}
			}
			if (abs(x - y) <= 1)
			{
				printf("%d\n", ans.size());
				for (auto k : ans)
				{
					printf("%d ", k);
				}
				cout << endl;
 
			}
			else
			{
				printf("%d\n", -1);
				continue;
			}
		}
	}
}

E题
题意:给出一个图,给出两个点a,b,问有多少对其他点,要求这对点的所有路径都经过给出的两个点。
先分析一下什么情况不行。当一个点,不通过a直接连接b,而且不通过b能直接连接到a,那么该点不能和其他任何点进行匹配。
换句话说,每一个点当且仅当,能直连a的时候,不能直连b,或者能直连b的时候不能直连a,该点符合题意。
我们去掉点a,dfs b点,去掉点b,dfs a点,最后再去除相同的项,就能找到上述满足题意的点。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e5 + 10;
const int node_N = 2e5 + 10;
vector<int>vec[node_N];
int t;
int n, m, a, b;
int vis[node_N];
set<int>s1, s2;
void dfs(int u,int flag)
{
	vis[u] = 1;
	for (auto k : vec[u])
	{
		if (!vis[k])
		{
			if (flag == 2)s2.insert(k);
			else s1.insert(k);
			dfs(k,flag);
		}
	}
}
int main()
{
	t = read();
	while (t--)
	{
		s1.clear(); s2.clear();
		memset(vis, 0, sizeof(vis));
		n = read(), m = read(), a = read(), b = read();
		upd(i, 0, n)vec[i].clear();
		int u, v;
		upd(i, 1, m)
		{
			u = read(), v = read();
			vec[u].push_back(v);
			vec[v].push_back(u);
		}
		vis[a] = 1;
		dfs(b,2);
		memset(vis, 0, sizeof(vis));
		vis[a] = 0; vis[b] = 1;
		dfs(a,1);
		vector<int>er;
		for (auto k : s1)
		{
		//	cout << "K" << k << endl;
			if (s2.count(k))
			{
				er.push_back(k);
				s2.erase(k);
			}
		}
		for (auto k : er)s1.erase(k);
		printf("%lld\n", 1ll * s1.size()*s2.size());
	}
	return 0;
}

F题
讲道理我觉得这个构造题蛮好的。
一开始我是这么做的,找到最大的相同数字,和相同数字的数量,做dp,令dp[i]表示宽为w的时候,最多能放多少个。然后暴力枚举w,找到最大。然后放置的时候我是先放上三角,再放下三角。
后来发现这样做没有过样例二,觉得很奇怪。
赛后看了看了别人的提交。发现自己脑残了。

正解:我们同样令dp[i]表示宽为w的时候,最多能放多少个。宽为w的时候,最多能放置,w个同样的数字。
我们以这样的思维来放置,从对角线出发放置,如果往右走到边界,跳到左边继续放置。这样能保证一定不重复。首先高不同,行内不重复。其次,如果跳转到左边,那么列不重复。倘若没有跳转,同一条对角线上,元素不重复,且我们优先计算了w,保证了最多w个同样的数字,即对角线个。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 4e5 + 10;
int n;
int a[N];
int dp[N];
map<int, int>mp1,num;
vector<pir>vec;
int main()
{
	n = read();
	upd(i, 1, n)
		a[i] = read();
	upd(i, 1, n)mp1[a[i]]++;
	int kind = 0;
	for (auto k : mp1)num[k.second]++,kind++;
	upd(i, 1, n)
	{
		dp[i] = dp[i - 1] + kind;
		kind -= num[i];
	}
	int now_h=0, now_w=0;
	upd(i, 1, n)
	{
		int w = dp[i] / i;
		if (w >= i) {
			if (now_h*now_w < w*i)
			{
				now_h = i;
				now_w = w;
			}
		}
	}
	printf("%d\n%d %d\n", now_h*now_w, now_h, now_w);
	for (auto k : mp1)vec.push_back(make_pair(k.second, k.first));
	sort(vec.begin(), vec.end(),greater<pir>());
	queue<int>que;
	for (auto k : vec)upd(i, 1, min(k.first, now_h))que.push(k.second);
	vector<vector<int> >ans(now_h, vector<int>(now_w, 0));
	up(j, 0, now_w)
	{
		int temp_w = j;
		up(i, 0, now_h)
		{
			ans[i][temp_w] = que.front(); que.pop();
		//	cout << ans[i][temp_w] << " " << "i" << i << " temp_w" << temp_w << endl;
			temp_w++; temp_w %= now_w;
		}
	}
	up(i, 0, now_h) {
		up(j, 0, now_w) {
			printf("%d ", ans[i][j]);
		}
		printf("\n");
	}
	return 0;
}
posted @ 2019-12-17 09:18  LORDXX  阅读(134)  评论(0编辑  收藏  举报