Codeforces Round 855 (Div. 3)

之前立下了一个flag,每个有空的下午做一套CF来增长智商。

题目地址

G. Symmetree

问题的本质如何快速比对两个子树是否相同。

考虑树hash。这里采用的是主流的AHU算法(安徽大学(不是)

主要将vector排序后放map里来获取hash值。

即vector就是一个键值。由于每个点只在父亲处贡献每个父亲只访问一次总复杂度是nlog的。

这样的hash显然是准确的。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 10000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define putl_(x) printf("%lld ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt
#define l(w) t[w].l
#define r(w) t[w].r
#define L(w) s[w].l
#define R(w) s[w].r
#define yy p<<1|1
#define zz p<<1
#define sum(w) t[w].sum
#define mod 1000000007
#define sc(A) scanf("%d",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define sub(x,y) (x-y<0?x-y+mod:x-y)
using namespace std;
const int MAXN=2000010,N=888,G=3;
int T,n,id,top,len;
int has[MAXN],ans[MAXN],s[MAXN];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1];
vector<int>g[MAXN];
map<vector<int>,int>H;
inline  void add(int x,int y)
{
	ver[++len]=y;
	nex[len]=lin[x];
	lin[x]=len;
}
inline void dfs(int x,int fa)
{
	g[x].clear();
	go(x)
	{
		if(tn==fa)continue;
		dfs(tn,x);
		g[x].pb(has[tn]);
	}
	sort(g[x].begin(),g[x].end());
	if(H.find(g[x])!=H.end())has[x]=H[g[x]];
	else H[g[x]]=++id,has[x]=id;
	top=0;
	rep(0,(int)g[x].size()-1,j)
	{
		if(top&&s[top]==g[x][j])--top;
		else s[++top]=g[x][j];
	}
	if(top>=2)ans[x]=-1;
	if(top==0)ans[x]=1;
	if(top==1)go(x)if(tn!=fa&&has[tn]==s[top])
	{
		ans[x]=ans[tn];
		break;
	}
}
int main()
{
	freopen("1.in","r",stdin);
	sc(T);
	while(T--)
	{
		sc(n);H.clear();
		len=0;id=0;
		rep(1,n,i)
		{
			lin[i]=0;
		}
		rep(2,n,i)
		{
			int x,y;
			sc(x);
			sc(y);
			add(x,y);add(y,x);
		}
		dfs(1,0);
		puts(ans[1]==1?"YES":"NO");
	}
	return 0;
}
F 数点问题。

仔细分析题目所给条件只需满足最后两个条件即可。

可以枚举某个字母是否出现,这样变成了两个串异或为全1的情况。

使用map来数点即可。

注意在查找是要先find一下避免增加不必要的键值,不然直接跑回超时。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 10000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define putl_(x) printf("%lld ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt
#define l(w) t[w].l
#define r(w) t[w].r
#define L(w) s[w].l
#define R(w) s[w].r
#define yy p<<1|1
#define zz p<<1
#define sum(w) t[w].sum
#define mod 1000000007
#define sc(A) scanf("%d",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define sub(x,y) (x-y<0?x-y+mod:x-y)
using namespace std;
const int MAXN=5000010,N=888,G=3;
int T,n,id,top,len;
char a[MAXN];
int w[MAXN];
map<int,int>H[26];
int main()
{
	//freopen("1.in","r",stdin);
	sc(n);
	int maxx=(1<<26)-1;
	ll ans=0;
	//int last=0;
	rep(1,n,i)
	{
		scs(a+1);
		int m=strlen(a+1);
		rep(1,m,j)
		{
			int x=a[j]-'a';
			++w[x];
		}
		int v=0,ww;
		for(int k=25;k>=0;--k)v=v<<1|(w[k]&1);
		rep(0,25,k)
		{
			if(!w[k])
			{
				ww=maxx^(1<<k);
				ww=ww^v;
				if(H[k].find(ww)!=H[k].end())ans+=H[k][ww];
				++H[k][v];
			}
			w[k]=0;
		}
		//cout<<(last^v)<<' '<<(maxx^(1<<25))<<endl;
	}
	putl(ans);
	return 0;
}

E 两个版本几乎相同。

仔细思考发现有一段区间的点可以任意交换。

还有一段连续区间不能交换。分别做判断就行。

有手就行。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 10000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define putl_(x) printf("%lld ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt
#define l(w) t[w].l
#define r(w) t[w].r
#define L(w) s[w].l
#define R(w) s[w].r
#define yy p<<1|1
#define zz p<<1
#define sum(w) t[w].sum
#define mod 1000000007
#define sc(A) scanf("%d",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define sub(x,y) (x-y<0?x-y+mod:x-y)
using namespace std;
const int MAXN=5000010,N=888,G=3;
int T,n,k,id,top,len;
char a[MAXN],b[MAXN];
int w[MAXN];
map<int,int>H[26];
int main()
{
	//freopen("1.in","r",stdin);
	sc(T);
	while(T--)
	{
		sc(n);sc(k);
		scs(a+1);
		scs(b+1);
		int flag=0;
		if(k>=n)
		{
			rep(1,n,i)if(a[i]!=b[i])flag=1;
			if(flag)puts("NO");
			else puts("YES");
			continue;
		}
		int cc=n-k+1;
		if(cc<=k)
		{
			rep(cc,k,i)if(a[i]!=b[i])flag=1;
			rep(1,cc-1,i)++w[a[i]-'a'],--w[b[i]-'a'];
			rep(k+1,n,i)++w[a[i]-'a'],--w[b[i]-'a'];
		}
		else rep(1,n,i)++w[a[i]-'a'],--w[b[i]-'a'];
		rep(0,25,i)
		{
			if(w[i])flag=1;
			w[i]=0;
		}
		if(flag)puts("NO");
		else puts("YES");
	}
	return 0;
}

既然E题有手就行其他题就不做了,下班。

posted @ 2023-03-15 16:46  chdy  阅读(55)  评论(0编辑  收藏  举报