Bubble Cup 11(Codeforces 1045) 简要题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82867060

传送门

Last chance

可以连两个的肯定可以增广,剩下的线段树优化见图跑网络流。

输出方案可以dfs反向边来退流。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=2e5+50, INF=0x3f3f3f3f;

int n,m,tot,bg,id[N],vis[N];
vector <pii> vec;
namespace mcmf {
	int g[N],nt[N],vt[N],c[N],ec=1;
	int cur[N],lev[N],que[N],hd,tl,src,des;
	int flow;
	inline void add(int x,int y,int cc) {
		nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; c[ec]=cc;
		nt[++ec]=g[y]; g[y]=ec; vt[ec]=x; c[ec]=0;
	}
	inline bool bfs() {
		for(int i=1;i<=des;i++) lev[i]=0;
		lev[que[hd=tl=1]=src]=1;
		while(hd<=tl) {
			int u=que[hd++];
			for(int e=g[u];e;e=nt[e]) {
				if(!c[e] || lev[vt[e]]) continue;
				lev[vt[e]]=lev[u]+1; que[++tl]=vt[e];
				if(vt[e]==des) return true;
			}
		} return false;
	}
	inline int dinic(int x,int f) {
		if(x==des) return f;
		int rs=0;
		for(int &e=cur[x];e;e=nt[e]) {
			if(!c[e] || (lev[vt[e]]!=lev[x]+1)) continue;
			int o=dinic(vt[e],min(f-rs,c[e]));
			c[e]-=o; c[e^1]+=o; rs+=o;
			if(rs==f) return rs;
		} return lev[x]=0, rs;
	}
	inline void maxflow() {
		int t;
		while(bfs()) {
			memcpy(cur+1,g+1,sizeof(int)*des);
			while((t=dinic(src,INF))) flow+=t, memcpy(cur+1,g+1,sizeof(int)*des);
		}
	}
}
using namespace mcmf;

inline void build(int k,int l,int r) {
	id[k]=++tot; 
	if(l==r) {mcmf::add(id[k],l,1); return;}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	add(id[k],id[k<<1],INF);
	add(id[k],id[k<<1|1],INF);
}
inline void inc(int k,int l,int r,int L,int R) {
	if(L<=l && r<=R) {add(tot,id[k],1); return;}
	int mid=(l+r)>>1;
	if(R<=mid) inc(k<<1,l,mid,L,R);
	else if(L>mid) inc(k<<1|1,mid+1,r,L,R);
	else inc(k<<1,l,mid,L,R), inc(k<<1|1,mid+1,r,L,R);
}

map <int,int> edge[N];
int tar;
inline void source(int x) {
	if(x>=bg) {tar=x-bg+1; return;}
	map <int,int> :: iterator it=edge[x].begin();
	source(it->first); --it->second;
	if(!it->second) edge[x].erase(it);
}
int main() {
	n=rd(), m=rd(); tot=m;
	mcmf::src=++tot;
	build(1,1,m);
	bg=tot+1;
	for(int i=1;i<=n;i++) {
		int type=rd(); ++tot;
		if(!type) {
			int k=rd();
			while(k--) add(tot,rd(),1);
			add(mcmf::src,tot,1);
		} else if(type==1) {
			int l=rd(), r=rd();
			inc(1,1,m,l,r);
			add(mcmf::src,tot,1);
		} else {
			int a=rd(), b=rd(), c=rd();
			vis[a]=vis[b]=1; flow+=2;
			add(tot,a,0); mcmf::c[ec]=1;
			add(tot,b,0); mcmf::c[ec]=1;
			add(tot,c,1);
		}
	}
	des=++tot;
	for(int i=1;i<=m;i++) if(!vis[i]) add(i,mcmf::des,1);
	
	maxflow();
	cout<<flow<<'\n';
	
	for(int i=1;i<=tot;i++)
		for(int j=g[i];j;j=nt[j])
			if((j&1) && c[j]) edge[i][vt[j]]=c[j];
	for(int i=1;i<=m;i++) {
		int tag=1;
		for(int e=g[i];e && tag;e=nt[e]) if(vt[e]==des && c[e]) tag=0;
		if(tag) source(i), printf("%d %d\n",tar,i);
	}
}

Space Isaac

一个数 t t 不能被凑出来,那么 t a i t-a_i 必须在 a a 集合中,也就是集合中的数可以两两配对。

从小到大排序后,因为相邻两个数的距离和配对的数的距离,用哈希判断是否所有距离相同。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

typedef unsigned long long ULL;
const ULL base=998244353;
const int mod=1e9+7;
const int N=2e5+50;
ULL pw[N], pre[N], suf[N];
int n,a[N],M;
unordered_map <int,int> mp;

int main() {
	n=rd(), M=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) mp[a[i]]=i;
	pw[0]=1;
	for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
	for(int i=2;i<=n;i++) pre[i]=pre[i-1]*base+a[i]-a[i-1];
	for(int i=n-1;i>=1;i--) suf[i]=suf[i+1]+pw[n-i-1]*(a[i+1]-a[i]);
	vector <int> vec;
	
	ULL hv(0);
	for(int i=2;i<=n;i++) hv=hv+pw[i-2]*(a[i]-a[i-1]);
	for(int i=1;i<=n;i++) {
		ULL tar;
		if(i!=n) tar=suf[i+1]*pw[i]+(a[1]-a[n]+M)*pw[i-1]+pre[i];
		else tar=suf[1];
		if(hv==tar) vec.push_back((a[1]+a[i])%M);
	}
	sort(vec.begin(),vec.end());
	printf("%d\n",vec.size());
	for(int i=0;i<vec.size();++i) printf("%d ",vec[i]);
}

Hyperspace Highways

建圆方树。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}
inline void W(int x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}

const int N=3e5+50, L=21;
int n,m,q,tot;
int dfn[N],low[N],vis[N],vs,ind;
int dep[N],fa[N][L];
stack <pii> e;
vector <int> g1[N];
vector <int> g2[N];

inline void dfs(int x,int f) {
	low[x]=dfn[x]=++ind;
	for(auto v:g1[x]) {
		int top=e.size();
		if(!dfn[v]) {
			dfs(v,x), low[x]=min(low[x],low[v]);
			e.push(pii(x,v));
			if(dfn[x]<=low[v]) {
				++vs; vector <int> vec;
				while(e.size()>top) {
					int u=e.top().first, v=e.top().second; e.pop();
					if(vis[u]!=vs) vis[u]=vs, vec.push_back(u);
					if(vis[v]!=vs) vis[v]=vs, vec.push_back(v);
				}
				++tot;
				for(auto j:vec) g2[tot].push_back(j), g2[j].push_back(tot);
			}
		} else if(v!=f) low[x]=min(low[x],dfn[v]);
	}
}
inline void dfs2(int x,int f) {
	fa[x][0]=f; dep[x]=dep[f]+1;
	for(int j=1;j<L;j++) fa[x][j]=fa[fa[x][j-1]][j-1];
	for(auto v:g2[x]) if(v!=f) dfs2(v,x);
}
inline int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	int d=dep[x]-dep[y];
	for(int i=0;i<L;i++) if((d>>i)&1) x=fa[x][i];
	if(x==y) return x;
	for(int i=L-1;~i;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];
	return fa[x][0];
}

int main() {
	n=rd(), m=rd(), q=rd(), tot=n;
	for(int i=1;i<=m;i++) {
		int x=rd(), y=rd();
		g1[x].push_back(y);
		g1[y].push_back(x);
	} dfs(1,0); dfs2(1,0);
	while(q--) {
		int x=rd(), y=rd();
		W((dep[x]+dep[y]-2*dep[lca(x,y)])/2), putchar('\n');
	}
}

Interstellar battle

一个点有贡献,那么父亲消失而且自己不消失。

#include <bits/stdc++.h>
using namespace std;

const int N=1e5+50;
int n,q,fa[N];
vector <int> g[N];
double p[N],s[N],ans;

inline void dfs(int x,int f) {
	ans+=p[f]*(1-p[x]);
	for(auto v:g[x]) if(v!=f) fa[v]=x, s[x]+=(1-p[v]), dfs(v,x);	
}

int main() {
	scanf("%d",&n); p[0]=1;
	for(int i=1;i<=n;i++) scanf("%lf",&p[i]);
	for(int i=1;i<n;i++) {
		int x,y; scanf("%d%d",&x,&y);
		++x; ++y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0);
	scanf("%d",&q);
	for(int i=1;i<=q;i++) {
		int x; double t;
		scanf("%d%lf",&x,&t); ++x;
		ans-=p[x]*s[x];
		ans-=p[fa[x]]*(1-p[x]);
		ans+=t*s[x];
		ans+=p[fa[x]]*(1-t);
		s[fa[x]]-=(1-p[x]);
		s[fa[x]]+=(1-t);
		p[x]=t;
		printf("%.5f\n",ans); 
	}
}

Ancient civilizations

先做凸包,如果凸包上颜色大于两段,则无解。

否则可以规约为三角形中两个端点颜色相同的问题,然后找到三角形内部的一个点继续划分即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=1e3+50;
int n,m,vis[N];
struct P {
	int x,y,col,id;
	P(int x=0,int y=0,int col=0,int id=0) : x(x),y(y),col(col),id(id) {}
	friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
	friend inline int operator *(const P &a,const P &b) {return a.x*b.y-a.y*b.x;}
} p[N],q[N];
typedef vector <P> vp;
typedef pair <int,int> pii;

vector <pii> ans;
inline void add(int x,int y) {ans.push_back(pii(x,y));}
inline bool in(P a,P b,P c,P d) {return (a-d)*(b-d)>0 && (b-d)*(c-d)>0 && (c-d)*(a-d)>0;}
inline void solve(P a,P b,P c) {
	for(int i=1;i<=n;i++) if(in(a,b,c,p[i]) && p[i].col!=a.col) {
		add(p[i].id,c.id);
		solve(c,p[i],b); 
		solve(a,b,p[i]); 
		solve(p[i],c,a);
		return;
	}
	vp vec;
	for(int i=1;i<=n;i++) if(in(a,b,c,p[i])) add(a.id,p[i].id);
}
int main() {
	n=rd();
	for(int i=1;i<=n;i++) p[i].x=rd(), p[i].y=rd(), p[i].col=rd(), p[i].id=i;
	if(n==2) {
		if(p[1].col^p[2].col) puts("1\n1 2");
		else puts("0");
		return 0;
	}
	sort(p+1,p+n+1,[&] (const P &a,const P &b) {return a.x<b.x || (a.x==b.x && a.y<b.y);});
	sort(p+2,p+n+1,[&] (const P &a,const P &b) {return (a-p[1])*(b-p[1])>0;});
	q[m=1]=p[1];
	for(int i=2;i<=n;i++) {
		while(m>=2 && (p[i]-q[m-1])*(q[m]-q[m-1])>0) --m;
		q[++m]=p[i];
	}
	int fir[2]={0,0}, lst[2]={0,0}, cnt=0;
	for(int i=1;i<=m;i++) {
		if(q[i].col!=q[i%m+1].col) {
			++cnt;
			if(cnt>2) {puts("Impossible"); return 0;}
			if(!fir[0]) {
				fir[0]=i, fir[1]=i%m+1;
				if(q[i].col!=q[(i==1) ? m : (i-1)].col) lst[1]=i, lst[0]=i%m+1;
			} else lst[1]=i, lst[0]=i%m+1;
		}
	}
	for(int i=1;i<=m;i++) vis[q[i].id]=1;
	if(!cnt) {
		int tag=0;
		for(int i=1;i<=n;i++) if(!vis[i] && p[i].col!=q[1].col) {
			for(int j=1;j<=m;j++) {
				if(j!=m) add(q[j].id,q[j+1].id);
				solve(q[j],q[j%m+1],p[i]);
			}
			tag=1; break;
		}
		if(!tag) for(int i=1;i<n;i++) add(p[i].id,p[n].id);
	} else {
		for(int i=fir[1];i!=lst[1];i=i%m+1) {
			add(q[i].id,q[i%m+1].id);
			solve(q[i],q[i%m+1],q[lst[0]]);
		}
		for(int i=lst[0];i!=fir[0];i=i%m+1) {
			add(q[i].id,q[i%m+1].id);
			solve(q[i],q[i%m+1],q[fir[1]]);
		}
	}
	cout<<ans.size()<<'\n';
	for(int i=0;i<ans.size();i++) cout<<ans[i].first-1<<' '<<ans[i].second-1<<'\n';
}

Shady Lady

题解太长了专门写了一篇:传送门

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=2e5+50;
int n,m,vis[N];
struct P {
	LL x,y; int id;
	P(LL x=0,LL y=0,int id=0) : x(x),y(y),id(id) {}
 	friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
	friend inline LL operator *(const P &a,const P &b) {return a.x*b.y-a.y*b.x;}
	inline LL norm() {return x*x+y*y;}
} p[N],q[N];

inline void build_conv(int nn) {
	m=1;
	sort(q+1,q+nn+1,[&] (const P &a,const P &b) {return (a.x<b.x) || (a.x==b.x && a.y<b.y) || (a.x==b.x && a.y==b.y && a.id<b.id);});
	sort(q+2,q+nn+1,[&] (const P &a,const P &b) {
		LL det=(a-q[1])*(b-q[1]);
		if(det!=0) return det>0;
		return (a-q[1]).norm()<(b-q[1]).norm();
	});
	
	for(int i=2;i<=nn;i++) {
		while(m>=2 && (q[i]-q[m-1])*(q[m]-q[m-1])>=0) --m;
		q[++m]=q[i];
	}
	
	for(int i=1;i<=m;i++) if(q[i].x&1 || q[i].y&1) {puts("Ani"); exit(0);}
}

int main() {
	n=rd()+1; p[1].id=1;
	for(int i=2;i<=n;i++) p[i].x=rd(), p[i].y=rd(), p[i].id=i;
	memcpy(q+1,p+1,sizeof(P)*(n));
	build_conv(n);
	
	for(int i=2;i<=m;i+=2) vis[q[i].id]=1, vis[q[i+1].id]=2;
	
	m=0;
	for(int i=1;i<=n;i++) if(vis[i]!=2) q[++m]=p[i];
	build_conv(m);
	
	m=0;
	for(int i=1;i<=n;i++) if(vis[i]!=1) q[++m]=p[i];
	build_conv(m);
	
	puts("Borna");
}

AI robots

暴力枚举 k k 的那一维,然后按照 r r 从小到大枚举,用树状数组维护。


 #include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=5e5+50;

int n,K; LL ans;
vector <int> cd;
vector <int> ck;
vector <int> pos[N];

inline int id(vector <int> &vec,int t) {return lower_bound(vec.begin(),vec.end(),t)-vec.begin();}

struct data {
	int x,r,k;
	friend inline bool operator <(const data &a,const data &b) {return a.r<b.r;}
} a[N];
 
struct fenwick_tree { 
	vector <int> all,bit;
	inline void init() {
		sort(all.begin(),all.end());
		all.erase(unique(all.begin(),all.end()),all.end());
		bit.resize(all.size()+1);
	}
	inline void inc(int x,int v) {
		int p=lower_bound(all.begin(),all.end(),x)-all.begin()+1;
		for(;p<=all.size();p+=p&(-p)) bit[p]+=v;
	}
	inline int ask(int x,int rs=0) {
		int p=upper_bound(all.begin(),all.end(),x)-all.begin();
		for(;p;p-=p&(-p)) rs+=bit[p];
		return rs;
	}
} bit[N];
inline void inc_seg(int l,int r,int k) {
	k=id(ck,k);
	bit[k].inc(l,1);
	bit[k].inc(r+1,-1);
}
inline int ask_point(int x,int l,int r) {
	l=lower_bound(ck.begin(),ck.end(),l)-ck.begin();
	r=upper_bound(ck.begin(),ck.end(),r)-ck.begin()-1;
	int cnt=0;
	for(int i=l;i<=r;i++) cnt+=bit[i].ask(x);
	return cnt;
}

int main() {
	n=rd(), K=rd();
	for(int i=1;i<=n;i++) {
		a[i].x=rd(), a[i].r=rd(), a[i].k=rd();
		cd.push_back(a[i].x);
		ck.push_back(a[i].k); 
	}
	sort(cd.begin(),cd.end());
	sort(ck.begin(),ck.end());
	cd.erase(unique(cd.begin(),cd.end()),cd.end());
	ck.erase(unique(ck.begin(),ck.end()),ck.end());
	
	for(int i=1;i<=n;i++) {
		int p=id(ck,a[i].k);
		bit[p].all.push_back(a[i].x-a[i].r);
		bit[p].all.push_back(a[i].x+a[i].r+1);
	}
	for(int i=0;i<ck.size();++i) bit[i].init();
	
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) {
		ans+=ask_point(a[i].x,a[i].k-K,a[i].k+K);
		inc_seg(a[i].x-a[i].r,a[i].x+a[i].r,a[i].k);
	}

	cout<<ans<<'\n';
}

Self-exploration

相当于告诉了你 0 , 1 0,1 各自的段数和个数。
对于每个固定的前缀算一下贡献,后面是个球盒问题。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N=1e5+50, mod=1e9+7;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (LL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}

struct Combin {
	int fac[N],ifac[N];
	Combin() {
		fac[0]=1;
		for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
		ifac[N-1]=power(fac[N-1],mod-2);
		for(int i=N-2;~i;i--) ifac[i]=mul(ifac[i+1],i+1);
	}
	inline int C(int a,int b) {return mul(fac[a],mul(ifac[b],ifac[a-b]));}
	inline int calc(int a,int b) {
		if(a<b) return 0;
		if(b==0) return a==0;
		return C(a-1,b-1);
		
	}
} C;

int n,c[2][2];
char A[N],B[N];
int a[N],lim;

inline int solve(char *lim) {
	int len=strlen(lim+1);
	if(len<n || ((c[0][1]+1!=c[1][0] && c[0][1]!=c[1][0]))) return 0;
	if(len>n) return mul(C.calc(c[1][1]+c[0][1]+1,c[0][1]+1),C.calc(c[0][0]+c[1][0],c[1][0]));
	for(int i=1;i<=n;i++) a[i]=lim[i]-'0';
	int c0=0,c1=0,d0=0,d1=0,ans=0;
	for(int i=1;i<=n;i++) {
		if(a[i]^a[i-1]) (a[i]==1) ? ++d1 : ++d0;
		(a[i]==1) ? ++c1 : ++c0;
		if(d1>c[0][1]+1 || d0>c[1][0] || c1>c[1][1]+c[0][1]+1 || c0>c[0][0]+c[1][0]) break;
		if(a[i+1]==1) {
			int res0=c[0][0]+c[1][0]-c0-1, res1=c[1][1]+c[0][1]+1-c1;
			int resd0=c[1][0]-d0-(a[i]!=0), resd1=c[0][1]+1-d1;
			if(resd1!=resd0 && resd1!=resd0+1) continue;
			ans=add(ans,mul(C.calc(res1,resd1),C.calc(res0+1,resd0+1))); 
		} else if(i==n) {
			if(c0==c[0][0]+c[1][0] && c1==c[1][1]+c[0][1]+1 && d0==c[1][0] && d1==c[0][1]+1) ++ans;
		} 
	}
	return ans;
}
int main() {
	scanf("%s%s",A+1,B+1);
	for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) cin>>c[i][j], n+=c[i][j];
	++n;
	int ans=dec(solve(B),solve(A));	
	int len=strlen(A+1);
	for(int i=2;i<=len;i++) 
		c[A[i-1]-'0'][A[i]-'0']--;
	ans=add(ans,(!c[0][0] && !c[1][0] && !c[0][1] && !c[1][1]));
	cout<<ans<<'\n'; 
} 

Palindrome Pairs

回文条件是加起来至多字母为奇数, 枚举是哪个字母就行了。

#include <bits/stdc++.h>
using namespace std;

const int N=1e6+50;
int n,sta[N]; char ch[N];
map <int,int> mp;
long long ans=0;
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		int len=(scanf("%s",ch+1),strlen(ch+1));
		for(int j=1;j<=len;j++) sta[i]^=1<<((ch[j]-'a'));
		ans+=mp[sta[i]];
		for(int j=0;j<26;j++) ans+=mp[sta[i]^(1<<j)];
		mp[sta[i]]++;
	} cout<<ans<<'\n';
}

Moonwalk challenge

端点处暴力枚举,其他哈希前缀和。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
typedef unsigned long long ULL;
#define data Data
inline void W(int x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) putchar(buf[buf[0]--]+'0');
}

const int N=2e5+50, L=21;
const ULL base=31;

int n,m,ans[N];
int fa[N][L],f2[N],val[N],dep[N]; 
ULL pw[N],ipw[N],upv[N]; 
vector <pii> edge[N];
struct data {
	ULL vv;
	int id,base,l;
	data(ULL vv,int id,int base,int l) : vv(vv), id(id), base(base), l(l) {}
	friend inline bool operator <(const data &a,const data &b) {return a.l>b.l;}
};
vector <data> qry[N];

inline void dfs_pre(int x,int f) {
	fa[x][0]=f; dep[x]=dep[f]+1; f2[x]=x;
	for(int i=1;i<L;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
	for(auto v:edge[x]) if(v.first^f) {
		val[v.first]=v.second; 
		upv[v.first]=upv[x]*base+val[v.first];
		dfs_pre(v.first,x);
	}
}
inline int up(int x,int d) {for(int i=0;i<L;i++) if((d>>i)&1) x=fa[x][i]; return x;}
inline int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	if(dep[x]>dep[y]) x=up(x,dep[x]-dep[y]);
	if(x==y) return x;
	for(int i=L-1;~i;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];
	return fa[x][0];
}

const int H=2333333;
struct Hash_Map {
	#define pii pair <ULL,int>
	vector <pii> cont[H];
	inline void insert(ULL x) {
		int p=x%H;
		for(int i=0;i<cont[p].size();++i) 
			if(cont[p][i].first==x) {++cont[p][i].second; return;}
		cont[p].push_back(pii(x,1));
	}
	inline int ask(ULL x) {
		int p=x%H;
		for(int i=0;i<cont[p].size();++i)
			if(cont[p][i].first==x) return cont[p][i].second; 
		return 0;
	}
	inline void del(ULL x) {
		int p=x%H;
		for(int i=0;i<cont[p].size();++i)
			if(cont[p][i].first==x) {
				if(cont[p][i].second>1) --cont[p][i].second;
				else cont[p].pop_back();
				return;
			}
	}
	#undef pii
} hs;

int lim;
inline void dfs(int x,int f) {
	f2[x]=fa[f2[x]][0];
	if(dep[x]>lim) hs.insert(upv[x]-upv[f2[x]]*pw[lim]);
	while(qry[x].size() && qry[x].back().l==lim) {
		data v=qry[x].back(); qry[x].pop_back();
		ans[v.id]+=hs.ask(v.vv)*v.base;
	}
	for(auto v:edge[x]) if(v.first^f) dfs(v.first,x);
	if(dep[x]>lim) hs.del(upv[x]-upv[f2[x]]*pw[lim]);
	
}

int main() {
	scanf("%d",&n);
	for(int i=1;i<n;i++) {
		int x,y; char ch[3];
		scanf("%d%d%s",&x,&y,ch+1);
		edge[x].push_back(pii(y,ch[1]));
		edge[y].push_back(pii(x,ch[1]));
	}
	pw[0]=1;
	for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
	dfs_pre(1,0);
	
	scanf("%d",&m);
	for(int i=1;i<=m;i++) {
		int x,y,f;
		scanf("%d%d",&x,&y);
		f=lca(x,y);
		static char ch[N];
		scanf("%s",ch+1); int len=strlen(ch+1);
		if(dep[x]-dep[f]>=len) {
			ULL val=0;
			for(int j=1;j<=len;j++) val=val+ch[j]*pw[j-1];
			qry[x].push_back(data(val,i,1,len));
			qry[up(x,dep[x]-dep[f]-len+1)].push_back(data(val,i,-1,len));
		} 
		if(dep[y]-dep[f]>=len) {
			ULL val=0;
			for(int j=0;j<len;j++) val=val+ch[len-j]*pw[j];
			qry[y].push_back(data(val,i,1,len));
			qry[up(y,dep[y]-dep[f]-len+1)].push_back(data(val,i,-1,len));
		}
		static int seq[300], tl;
		if(x!=f && y!=f && len>1) {
			tl=0;
			int u=up(x,max(0,dep[x]-dep[f]-len+1));
			for(;u!=f;u=fa[u][0]) seq[++tl]=u;
			int top=tl;
			u=up(y,max(0,dep[y]-dep[f]-len+1));
			for(;u!=f;u=fa[u][0]) seq[++tl]=u;
			if(tl<len) continue;
			reverse(seq+top+1,seq+tl+1);
			ULL v=0,v2=0;
			for(int j=0;j<len;j++) v=v+ch[len-j]*pw[j];
			for(int j=1;j<=len;j++) v2=v2+val[seq[j]]*pw[len-j];
			ans[i]+=(v==v2);
			for(int j=len+1;j<=tl;++j) {
				v2=v2-val[seq[j-len]]*pw[len-1];
				v2=v2*base+val[seq[j]];
				ans[i]+=(v==v2); 
			}
		}
	}
	for(int i=1;i<=n;i++) sort(qry[i].begin(),qry[i].end());
	for(int i=1;i<=100;i++) {
		lim=i;
		dfs(1,0);
	}
	for(int i=1;i<=m;i++) W(ans[i]), putchar('\n');
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/82867060