Codeforces Round #855 (Div. 3)

Preface

以后有时间就把Div3后面的题写下看下,权当是保持状态了


E1. Unforgivable Curse (easy version)&&E2. Unforgivable Curse (hard version)

直接讲E2做法了,然后记得先判断每种字符出现次数是否相等

首先我们不难发现一个位置如果可以往某个方向换个\(k\),然后再往另一个方向换\(k+1\),就可以实现相邻位置的交换

而我们知道相邻位置的交换可以实现任意位置的交换,因此不难发现对于大部分位置我们都可以任意交换

那么只有那些一开始就没法进行操作的位置是固定的,特判它们即可

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int t,n,k,c1[26],c2[26]; char a[N],b[N];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; for (scanf("%d%d%s%s",&n,&k,a+1,b+1),i=0;i<26;++i) c1[i]=c2[i]=0;
		for (i=1;i<=n;++i) ++c1[a[i]-'a'],++c2[b[i]-'a'];
		bool flag=1; for (i=0;i<26&&flag;++i) if (c1[i]!=c2[i]) flag=0;
		if (!flag) { puts("NO"); continue; }
		for (i=1;i<=n&&flag;++i) if (i-k<1&&i+k>n&&a[i]!=b[i]) flag=0;
		puts(flag?"YES":"NO");
	}
	return 0;
}

F. Dasha and Nightmares

先考虑字符出现次数为奇数这个条件,不难想到可以状压每个字符出现的次数的奇偶性

由于奇偶性的加减类似于异或,因此我们可以通过用目标状态异或当前状态来得到与之匹配的另一个状态

但是这样会有一个问题,我们只保证有\(25\)个字符出现次数为奇数,但不能保证恰好出现了\(25\)种字符(即可能有剩下一个字符出现了非零偶数次)

那么考虑在统计个数的桶上加一维,表示这个串中没有出现某个字符,然后枚举的时候要两个串都没有这个字符才能统计

由于时空限制很死,直接开数组会MLE,用map会TLE,因此祭出unordered_map大法

总复杂度\(O(26n)\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<unordered_map>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int n,m,c[26],vis[26],tar[26]; unordered_map <int,int> bkt[26]; char s[5000005]; long long ans;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (i=0;i<26;++i) tar[i]=((1<<26)-1)^(1<<i);
	for (scanf("%d",&n),ans=0,i=1;i<=n;++i)
	{
		for (j=0;j<26;++j) c[j]=vis[j]=0;
		for (scanf("%s",s+1),m=strlen(s+1),j=1;j<=m;++j) vis[s[j]-'a']=1,c[s[j]-'a']^=1;
		int cur=0; for (j=0;j<26;++j) cur|=(c[j]<<j);
		for (j=0;j<26;++j) if (!vis[j]) ++bkt[j][cur];
		for (j=0;j<26;++j) if (!vis[j]) ans+=bkt[j][cur^tar[j]];
	}
	return printf("%lld\n",ans),0;
}

G. Symmetree

树Hash裸题,关于树Hash的知识可以看这里

这道题的话我们直接统计每个点的所有子节点的Hash值,如果都能两两配对则这个点的子树是对称的

如果不能对称那就看下单独多出的那一个,它的子树是否对称

这里为了练习所以写了两种方法的CODE

随机种子+子树异或+shift(可能被卡,复杂度\(O(n)\)

#include<cstdio>
#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
typedef unsigned long long u64;
int t,n,x,y,sym[N]; vector <int> v[N]; u64 seed,hsh[N];
inline u64 shift(u64 x)
{
	x^=x<<13; x^=x>>7; x^=x<<17; return x;
}
inline void DFS(CI now=1,CI fa=0)
{
	u64 sum=seed,xsum=0; for (int to:v[now]) 
	if (to!=fa) DFS(to,now),sum+=shift(hsh[to]),xsum^=shift(hsh[to]);
	hsh[now]=sum; if (!xsum) sym[now]=1; else
	for (int to:v[now]) if (to!=fa&&shift(hsh[to])==xsum&&sym[to]) { sym[now]=1; break; }
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		srand(time(0)); seed=1ull*rand()*rand()*rand()*rand()*rand();
		RI i; for (scanf("%d",&n),i=1;i<=n;++i) v[i].clear(),sym[i]=0;
		for (i=1;i<n;++i) scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
		DFS(); puts(sym[1]?"YES":"NO");
	}
	return 0;
}

AHU算法(绝对正确,复杂度\(O(n\log n)\)

#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
typedef vector <int> VI;
int t,n,x,y,idx,sym[N],hsh[N]; VI v[N]; map <VI,int> rst;
inline void DFS(CI now=1,CI fa=0)
{
	VI tmp; map <int,int> cnt; for (int to:v[now])
	if (to!=fa) DFS(to,now),tmp.push_back(hsh[to]);
	sort(tmp.begin(),tmp.end());
	if (!rst[tmp]) rst[tmp]=++idx; hsh[now]=rst[tmp];
	for (int to:v[now]) if (to!=fa) ++cnt[hsh[to]];
	int cur=0,p; for (auto &[c,t]:cnt) if (t&1) ++cur,p=c;
	if (!cur) sym[now]=1; else if (cur==1)
	for (int to:v[now]) if (to!=fa&&hsh[to]==p) sym[now]|=sym[to];
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; for (scanf("%d",&n),i=1;i<=n;++i) v[i].clear(),sym[i]=0;
		for (i=1;i<n;++i) scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
		idx=0; rst.clear(); DFS(); puts(sym[1]?"YES":"NO");
	}
	return 0;
}

Postscript

最近CF的时间太阴间了,想找场比赛打真是不容易的说

posted @ 2023-03-03 10:13  空気力学の詩  阅读(400)  评论(2编辑  收藏  举报