CF Round #805 (Div. 3) 题解

A

直接模拟即可,注意 10k 的情况(罚时!罚时!罚时!).

A Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
ll n;
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		scanf("%lld", &n); ll t = n;
		ll x = 1;
		bool flag = true;
		while (n >= 10){flag &= !(n % 10); n /= 10; x *= 10;}
		if (flag && (n == 1)) puts("0");
		else printf("%lld\n", t - x);
	} return 0;
}

B

用一个 std::set 扫一遍即可 .

B Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
string s;
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		cin >> s; int ans = 0, l = s.length();
		set<char> se;
		for (int i=0; i<l; i++)
		{
			se.insert(s[i]);
			if (se.size() > 3){se.clear(); se.insert(s[i]); ++ans;}
		}
		printf("%d\n", ans + 1);
	} return 0;
}

C

不难发现如果可以必然是 bi 最后一次出现的位置不小于 ai 第一次出现的位置 .

std::set 判是否在序列中,std::map 存出现位置即可 .

C Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 114514;
map<int, pii> M; // fst, sec
set<int> s;
int n, k, a[N];
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		s.clear(); M.clear();
		scanf("%d%d", &n, &k);
		for (int i=1; i<=n; i++)
		{
			scanf("%d", a+i);
			if (s.find(a[i]) == s.end()) M[a[i]] = make_pair(i, i);
			else M[a[i]].second = i;
			s.insert(a[i]);
		}
		int p, q;
		while (k--)
		{
			scanf("%d%d", &p, &q);
			if ((s.find(p) == s.end()) || (s.find(q) == s.end())){puts("NO"); continue;}
			if (M[q].second > M[p].first) puts("YES");
			else puts("NO");
		}
	} return 0;
}

D

贪心地删掉权值最大的字符即可 .

D Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
constexpr int N = 514514;
string s;
int w;
vector<pii> vec;
inline bool cmp1(const pii& a, const pii& b)
{
	return a.first == b.first ? a.second < b.second : a.first < b.first;
}
inline bool cmp2(const pii& a, const pii& b)
{
	return a.second == b.second ? a.first < b.first : a.second < b.second;
}
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		vec.clear();
		cin >> s; int l = s.length();
		scanf("%d", &w); int p = 0;
		for (int i=0; i<l; i++) vec.emplace_back(make_pair(s[i]-'a', i)), p+=s[i]-'a'+1;
		stable_sort(vec.begin(), vec.end(), cmp1);
		while (!vec.empty() && (p > w)){p -= vec.back().first + 1; vec.pop_back();}
		stable_sort(vec.begin(), vec.end(), cmp2);
		for (pii x : vec) putchar(x.first+'a');
		puts("");
	}
	return 0;
}

E

首先排除掉一些显然不对的情况,例如 {a,a} 或者出现次数大于 2 .

然后对于每个 {a,b}a,b 肯定不能同时选,于是连边 ab,因为要分成两份所以黑白染色判是否是二分图即可 .

E Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
constexpr int N = 514514;
int n, cc[N];
vector<int> g[N];
inline void addedge(int u, int v){g[u].emplace_back(v);}
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
int col[N];
bool dfs(int u, int c)
{
	col[u] = c;
	for (int v : g[u])
		if ((col[v] == c) || (!col[v] && !dfs(v, 3 - col[u]))) return false;
	return true;
}
int main()
{
	int T; scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		bool _ = false;
		for (int i=1, u, v; i<=n; i++)
		{
			scanf("%d%d", &u, &v); ade(u, v);
			if (u == v) _ = true;
			++cc[u]; ++cc[v];
		}
		for (int i=1; i<=n; i++)
			if (cc[i] > 2){_ = true; break;}
		if (_){puts("NO"); goto ed;} // no goto  -- Dijkstra
		_ = true;
		for (int i=1; i<=n; i++)
			if (!col[i] && !dfs(i, 1)){puts("NO"); _ = false; break;}
		if (_) puts("YES");
	ed:
		for (int i=1; i<=n; i++){cc[i] = col[i] = 0; g[i].clear();}
	}
	return 0;
}

F

ABC 原题:ABC254H .

代码略

G1, G2

G1 直接暴力

G2 首先把所有点的 LCA 求出来 .

然后按深度排序,判两两 LCA 是否等于它们本身或所有点的 LCA 即可 .

G1 Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
constexpr int N = 514514, LgN = __lg(N) + 1;
int n, dep[N], f[N][LgN];
vector<int> g[N];
inline void addedge(int u, int v){g[u].emplace_back(v);}
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
void dfs(int u, int fa)
{
	f[u][0] = fa; dep[u] = dep[fa] + 1;
	for (int i=1; i<LgN; i++) f[u][i] = f[f[u][i-1]][i-1];
	for (int v : g[u])
		if (v != fa) dfs(v, u);
}
inline int lca(int p1, int p2)
{
	if (dep[p1] < dep[p2]) swap(p1,p2);
	for (int i=LgN-1; i>=0; i--)
		if (dep[f[p1][i]] >= dep[p2]) p1 = f[p1][i];
	if (p1 == p2) return p2;
	for (int i=LgN-1; i>=0; i--)
		if (f[p1][i] != f[p2][i]){p1 = f[p1][i]; p2 = f[p2][i];}
	return f[p1][0];
}
int main()
{
	scanf("%d", &n);
	for (int i=1, u, v; i<n; i++) scanf("%d%d", &u, &v), ade(u, v);
	dfs(1, 0);
	int q, k;
	scanf("%d", &q);
	while (q--)
	{
		vector<int> nd; vector<bool> vis;
		scanf("%d", &k); nd.resize(k); vis.resize(n+10);
		int core = 0, core2 = 0, fake = 0;
		for (int i=0; i<k; i++)
		{
			scanf("%d", &nd[i]);
			if (!core2) core2 = nd[i];
			else core2 = lca(core2, nd[i]);
		}
		++k; nd.emplace_back(core2);
		sort(nd.begin(), nd.end());
		nd.erase(unique(nd.begin(), nd.end()), nd.end());
		k = nd.size();
		for (int i=0; i<k; i++)
		{
			if (!core || (dep[nd[i]] < dep[core])) core = nd[i];
			if (!fake || (dep[nd[i]] > dep[fake])) fake = nd[i];
		}
		int u = fake;
		while (u && (u != core)){vis[u] = true; u = f[u][0];}
		vis[u] = true;
		if (!u){puts("NO"); continue;}
		fake = 0;
		for (int i=0; i<k; i++)
		{
			if (vis[nd[i]]) continue;
			if (!fake || (dep[nd[i]] > dep[fake])) fake = nd[i];
		}
		if (!fake){puts("YES"); continue;}
		u = fake;
		bool f = false;
		while (u && (u != core))
		{
			if (vis[u]){puts("NO"); f = true; break;}
			vis[u] = true; u = ::f[u][0];
		} vis[u] = true;
		if (f) continue;
		for (int i=0; i<k; i++)
			if (!vis[nd[i]]){puts("NO"); f = true; break;}
		if (f) continue;
		if (!u){puts("NO"); continue;}
		puts("YES");
	}
	return 0;
}
G2 Code
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
constexpr int N = 514514, LgN = __lg(N) + 1;
int n, dep[N], f[N][LgN];
vector<int> g[N];
inline void addedge(int u, int v){g[u].emplace_back(v);}
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
void dfs(int u, int fa)
{
	f[u][0] = fa; dep[u] = dep[fa] + 1;
	for (int i=1; i<LgN; i++) f[u][i] = f[f[u][i-1]][i-1];
	for (int v : g[u])
		if (v != fa) dfs(v, u);
}
inline int lca(int p1, int p2)
{
	if (dep[p1] < dep[p2]) swap(p1,p2);
	for (int i=LgN-1; i>=0; i--)
		if (dep[f[p1][i]] >= dep[p2]) p1 = f[p1][i];
	if (p1 == p2) return p2;
	for (int i=LgN-1; i>=0; i--)
		if (f[p1][i] != f[p2][i]){p1 = f[p1][i]; p2 = f[p2][i];}
	return f[p1][0];
}
vector<int> nd;
vector<bool> vis;
vector<int> l;
int main()
{
	scanf("%d", &n);
	for (int i=1, u, v; i<n; i++) scanf("%d%d", &u, &v), ade(u, v);
	dfs(1, 0);
	int q, k;
	scanf("%d", &q);
	while (q--)
	{
		scanf("%d", &k); nd.clear(); nd.resize(k); vis.clear(); vis.resize(n+1); l.clear();
		int core = 0;
		for (int i=0; i<k; i++)
		{
			scanf("%d", &nd[i]);
			if (!core || (dep[nd[i]] < dep[core])) core = nd[i];
		}
		if ((k == 1) || (k == 2)){puts("YES"); continue;}
		int cc = 0;
		for (int i=0; i<k; i++) cc += (dep[core] == dep[nd[i]]); 
		if (cc > 2){puts("NO"); continue;}
		for (int i=0; i<k; i++)
		{
			int tmp = lca(core, nd[i]);
			if (dep[tmp] < dep[core]) core = tmp;
		}
		stable_sort(nd.begin(), nd.end(), [](int i, int j){return dep[i] > dep[j];});
		bool flag = true;
		cc = 0;
		for (int i=0; i<k; i++)
		{
			int u = nd[i], v;
			if ((nd[i] == core) || vis[u]) continue;
			l.emplace_back(u); ++cc;
			if (cc > 2){flag = false; break;}
			for (int j=0; j<k; j++)
			{
				v = nd[j];
				if ((i == j) || vis[v]) continue;
				if ((lca(u, v) == v) && (lca(u, core) == core) && (lca(v, core) == core)) vis[v] = true;
			}
		}
		if (cc == 2)
		{
			int t = lca(l[0], l[1]);
			if ((t != core) && (t != l[0]) && (t != l[1])){puts("NO"); continue;}
		}
		if (flag) puts("YES");
		else puts("NO");
	}
	return 0;
}
posted @   yspm  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示