ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #808 (Div. 1)(A~C)

2022-07-17 10:01:23  阅读:152  来源: 互联网

标签:tmp 非树边 int Codeforces -- 808 Div include define


Codeforces Round #808 (Div. 1)(A~C)

A:Doremy's IQ

题目大意

给你一个序列,然后你从左到右可以选择弄或者不弄。
然后你有一个智商值,如果你当前弄的数小于等于它就无影响,否则智商值减一,如果变成了 \(0\) 就无法操作。
要你最大化弄的次数,并构造方案。

思路

小溪了这题就卡了半天。
甚至不如先做 T2。

正着我们会有一个 DP,但是似乎不太能优化。
所以考虑反着来,会发现问题就变成了一开始你是 \(0\),每次如果碰到大于的你可以选择 \(+1\) 并通过它,然后你只能加到 \(q\)。
会发现显然可以贪心,就能 \(+1\) 就加一,然后模拟一遍过程就好了。

代码

#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
//#define mo 998244353
//#define mo 1000000007

using namespace std;

const int N = 1e5 + 100;
int T, n, q, a[N], jian[N], big, newbig;
int ans[N];

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d %d", &n, &q);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]), ans[i] = 0;
		if (q >= n) {
			for (int i = 1; i <= n; i++) putchar('1'); putchar('\n'); continue;
		}
		int now = 0;
		for (int i = n; i >= 1; i--)
			if (now < a[i]) {
				if (now == q) continue;
				now++; ans[i] = 1;
			}
			else {
				ans[i] = 1;
			}
		for (int i = 1; i <= n; i++) printf("%d", ans[i]);
		printf("\n");
	}
	
	return 0;
}

B:Difference Array

题目大意

给你一个排好序数组,你要对它不断进行以下操作直至数组长度变为 \(1\),并输出最后的数。
把它差分,把差分得到的数组排序。

思路

我只能说有点诈骗。
首先发现数组每一项的和只会最多是数组长度的两倍。

那很多地方都会相同, 那因为一开始就排好序所以差分就会有很多 \(0\)。
然后你会你只需要保留一个 \(0\) 来进行操作,所以真正操作的量会很少。
所以直接模拟即可。

代码

#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
//#define mo 998244353
//#define mo 1000000007

using namespace std;

const int N = 1e5 + 100;
int T, n, a[N], l, r, tmp[N];

void work() {
	for (int i = l; i < r; i++) tmp[i] = a[i + 1] - a[i];
	sort(tmp + l, tmp + r);
	for (int i = l; i < r; i++) a[i] = tmp[i];
	if (l > 1) l--; r--;
}

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		l = 1; r = n; while (l < r && !a[l] && !a[l + 1]) l++;
		for (int i = 1; i < n; i++) {
			work();
			while (l < r && !a[l] && !a[l + 1]) l++;
		}
		printf("%d\n", a[l]);
	}
	
	return 0;
}

C:DFS Trees

题目大意

给你一个图,然后问你从每个点出发得到的 dfs 树是否是最小生成树。
每条边边权不同且为 \(1\sim m\) 的值。

思路

麻用错性质想了半天。(虽然看起来想法能写但来不及了,主要是想到的性质太复杂啦)

你会发现因为是最小生成树所以你对于一条非树边,你如果从一段走过去,你还是优先走树边。
那怎样会出现问题呢?就是你走完树边,发现到不了非树边连的点,那你就只能走非树边了。
画个图理解一下,你就会发现这些不行的位置都是在非树边两个点之间的路径上的点(以及它的子树),就是中间的部分,你只要从一头进去都是没问题的。

那我们考虑对每条非树边都得到一些判断:
从某些点出发 dfs 可以某些不行,具体一点我们把非树边 \(x,y\) 在树上的路径断开,然后 \(x,y\) 的子树是可以的。
那如果一个点要完全可以,它要满足每条非树边的条件,那我们就维护每个点满足了多少了条件。
至于子树赋值就直接打标记然后最后跑个 dfs 下传下去即可。

代码

#include<cstdio>
#include<vector>

using namespace std;

const int N = 1e5 + 100;
int n, m, fa[N], sum[N], go[N];
vector <int> g[N], G[N], bh[N];
bool tree[N << 1], in[N];

int find(int now) {return fa[now] == now ? now : fa[now] = find(fa[now]);}

void dfs(int now, int father) {
	in[now] = 1;
	for (int i = 0; i < g[now].size(); i++) { int x = g[now][i];
		if (x == father) continue;
		go[now] = x; dfs(x, now);
	}
	for (int i = 0; i < G[now].size(); i++) { int x = G[now][i];
		if (tree[bh[now][i]]) continue;
		tree[bh[now][i]] = 1;
		if (!in[x]) sum[now]++, sum[x]++;
			else sum[now]++, sum[1]++, sum[go[x]]--;
	}
	in[now] = 0;
}

void get_sum(int now, int father) {
	for (int i = 0; i < g[now].size(); i++) { int x = g[now][i];
		if (x == father) continue;
		sum[x] += sum[now]; get_sum(x, now);
	}
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) fa[i] = i;
	for (int i = 1; i <= m; i++) {
		int x, y; scanf("%d %d", &x, &y);
		if (find(x) != find(y)) fa[find(x)] = find(y), tree[i] = 1, g[x].push_back(y), g[y].push_back(x);
			else G[x].push_back(y), bh[x].push_back(i), G[y].push_back(x), bh[y].push_back(i);
	}
	
	dfs(1, 0);
	get_sum(1, 0);
	
	for (int i = 1; i <= n; i++)
		printf("%d", (sum[i] == m - (n - 1)) ? 1 : 0);
	
	return 0;
}

标签:tmp,非树边,int,Codeforces,--,808,Div,include,define
来源: https://www.cnblogs.com/Sakura-TJH/p/16485973.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有