ICode9

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

省选模拟15

2022-02-15 08:00:07  阅读:129  来源: 互联网

标签:f2 ch 15 省选 res rz int return 模拟


T1

把两位看成一组,分别维护把 \(0\) 合并进去能否出来 \(0/1\) 和把 \(1\) 合并进去能否出来 \(0/1\)

转移合并时有两种,一种是先把下一次进来的第一位和之前的合并再合并最后三个

另一种是先合并最后三个再合并前面的

Code
#include<bits/stdc++.h>
//#define int long long
#define rint signed
#define mod 998244353
#define F(a,b) for(int i=((a==2)?(0):(a));i<=((a==2)?(1):(a));i++) for(int j=((b==2)?(0):(b));j<=((b==2)?(1):(b));j++)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int T,n,ans;
int trans[10],sta0,sta1,sta;
char s1[10],s2[100010];
int f[100010][4][4];
inline int gsta(int a,int b,int c){return (c<<2)|(b<<1)|(a);}
inline void md(int &x){x=(x>=mod)?(x-mod):(x);}
inline int check(int t0,int t1,int a,int b,int u,int v){
	if(trans[gsta(a,b,u)]==1) if((t1>>v)&1) return 1;
	if(trans[gsta(a,b,u)]==0) if((t0>>v)&1) return 1;
	if(a==1){
		if(t1&1) if(trans[gsta(0,b,u)]==v) return 1;
		if(t1&2) if(trans[gsta(1,b,u)]==v) return 1;
	}else{
		if(t0&1) if(trans[gsta(0,b,u)]==v) return 1;
		if(t0&2) if(trans[gsta(1,b,u)]==v) return 1;
	}
	return 0;
}
inline void solve(){
	memset(f,0,sizeof(f));ans=0;
	scanf("%s%s",s1,s2+1);n=strlen(s2+1);
	for(int i=0;i<8;i++) trans[i]=s1[i]-'0';
	for(int i=1;i<=n;i++) s2[i]=(s2[i]=='?')?(2):(s2[i]-'0');
	F(s2[1],s2[2]){
		sta0=trans[gsta(i,j,0)];sta1=trans[gsta(i,j,1)];
		sta0=1<<(sta0),sta1=1<<(sta1);
		f[2][sta0][sta1]++;
	}
	for(int now=2;now<=n-3;now+=2) for(int v0=0;v0<4;v0++) for(int v1=0;v1<4;v1++) if(f[now][v0][v1]){
		F(s2[now+1],s2[now+2]){
			int v00,v01,v10,v11;
			v00=check(v0,v1,i,j,0,0);
			v01=check(v0,v1,i,j,0,1);
			v10=check(v0,v1,i,j,1,0);
			v11=check(v0,v1,i,j,1,1);
			sta0=(v00)|(v01<<1),sta1=(v10)|(v11<<1);
			md(f[now+2][sta0][sta1]+=f[now][v0][v1]);
		}
	}
	if(s2[n]==2){
		for(int v0=0;v0<4;v0++) for(int v1=0;v1<4;v1++) if(((v1>>1)&1)) md(ans+=f[n-1][v0][v1]);
		for(int v0=0;v0<4;v0++) for(int v1=0;v1<4;v1++) if(((v0>>1)&1)) md(ans+=f[n-1][v0][v1]);
	}
	else if(s2[n]==1){for(int v0=0;v0<4;v0++) for(int v1=0;v1<4;v1++) if(((v1>>1)&1)) md(ans+=f[n-1][v0][v1]);}
	else{for(int v0=0;v0<4;v0++) for(int v1=0;v1<4;v1++) if(((v0>>1)&1)) md(ans+=f[n-1][v0][v1]);}
	printf("%d\n",ans);
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	T=read();while(T--) solve();
	return 0;
}

T2

发现每个点的 \(SG\) 函数值跟儿子子树内最深的儿子有关

而且只会有两种取值,最大的记录为 \(f1\) 次大的为 \(f2\)

再以树的中心为根时,所有点都会取到 \(f2\) ,因为贡献最大的那个儿子一定会跨过中心

在以任意一个点 \(x\) 为根时,只有 \(x\) 到中心的路径上的点会取到 \(f1\)

用树剖和线段树维护一下异或和就行

实现上有点细节要特判一下中心的取值

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,rz,rx;
int f1[200010],f2[200010],s1,s2;
int dfn[200010],top[200010],siz[200010],fa[200010],dep[200010],son[200010],id[200010],clo;
vector<int>g[200010];
struct Seg{int a1,a2,b1,b2;bool atag;}st[200010*4];
bool ot;
void dfs0(int x,int fath){dep[x]=dep[fath]+1;fa[x]=fath;for(auto y:g[x]) if(y!=fath) dfs0(y,x);}
void dfs1(int x,int fath,int depth){
	fa[x]=fath,siz[x]=1,dep[x]=depth,f2[x]=0;
	int maxson=-1;
	for(auto y:g[x]) if(y!=fath){
		dfs1(y,x,depth+1);siz[x]+=siz[y];f2[x]=max(f2[x],f2[y]+1);
		if(maxson<siz[y]) son[x]=y,maxson=siz[y];
	}
}
void dfs2(int x,int topf){
	top[x]=topf;dfn[x]=++clo;id[clo]=x;
	if(!son[x]) return ;dfs2(son[x],topf);
	for(auto y:g[x]) if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
inline int getson(int x,int y){
	if(dfn[son[x]]<=dfn[y]&&dfn[y]+siz[y]-1<=dfn[son[x]]+siz[son[x]]-1) return son[x];
	for(;fa[y]!=x;y=top[fa[y]]);return y;
}
inline void pushup(int rt){
	st[rt].a1=st[lson].a1^st[rson].a1;
	st[rt].a2=st[lson].a2^st[rson].a2;
}
inline void pushdown(int rt){
	if(st[rt].atag){
		st[lson].atag^=1,st[rson].atag^=1;
		st[lson].a1^=st[lson].b1,st[lson].a2^=st[lson].b2;
		st[rson].a1^=st[rson].b1,st[rson].a2^=st[rson].b2;
		st[rt].atag=0;
	}
}
void build(int rt,int l,int r){
	if(l==r) return st[rt].a1=st[rt].b1=f2[id[l]],st[rt].a2=st[rt].b2=f1[id[l]]^f2[id[l]],void();
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(rt);
	st[rt].b1=st[lson].b1^st[rson].b1;
	st[rt].b2=st[lson].b2^st[rson].b2;
}
void upd(int rt,int l,int r,int L,int R){
	if(L<=l&&r<=R) return st[rt].atag^=1,st[rt].a1^=st[rt].b1,st[rt].a2^=st[rt].b2,void();
	int mid=(l+r)>>1;pushdown(rt);
	if(L<=mid) upd(lson,l,mid,L,R);
	if(R>mid) upd(rson,mid+1,r,L,R);
	pushup(rt);
}
int query1(int rt,int l,int r,int L,int R){
	if(L<=l&&r<=R) return st[rt].a1;
	int mid=(l+r)>>1,res=0;pushdown(rt);
	if(L<=mid) res^=query1(lson,l,mid,L,R);
	if(R>mid) res^=query1(rson,mid+1,r,L,R);
	return res;
}
int query2(int rt,int l,int r,int L,int R){
	if(L<=l&&r<=R) return st[rt].a2;
	int mid=(l+r)>>1,res=0;pushdown(rt);
	if(L<=mid) res^=query2(lson,l,mid,L,R);
	if(R>mid) res^=query2(rson,mid+1,r,L,R);
	return res;
}
inline void upd(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		upd(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	if(dfn[x]==1) ot^=1;upd(1,1,n,dfn[x],dfn[y]);
}
inline void upd(int x){
	if(x==rx) return upd(1,1,n,1,n),ot^=1,void();
	if(dfn[x]<=dfn[rx]&&dfn[rx]+siz[rx]-1<=dfn[x]+siz[x]-1){
		x=getson(x,rx);
		if(dfn[x]-1>=1) upd(1,1,n,1,dfn[x]-1),ot^=1;
		if(dfn[x]+siz[x]<=n) upd(1,1,n,dfn[x]+siz[x],n);
		return ;
	}
	if(dfn[x]==1) ot^=1;upd(1,1,n,dfn[x],dfn[x]+siz[x]-1);
}
inline int solve(int x){
	int res=query1(1,1,n,2,n),sx=0;rx=x;
	if(x!=rz) sx=getson(rz,x);
	while(top[x]!=top[rz]){
		res^=query2(1,1,n,dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if(dfn[rz]+1<=dfn[x]) res^=query2(1,1,n,dfn[rz]+1,dfn[x]);
	if(ot) res^=((sx==s1)?(f2[s2]+1):(f2[s1]+1));
	return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	n=read(),m=read();rx=1;ot=1;f1[0]=f2[0]=-1;
	for(int i=1,x,y;i<n;i++){
		x=read(),y=read();
		g[x].emplace_back(y);
		g[y].emplace_back(x);
	}
	dep[1]=0;dfs0(1,0);for(int i=1;i<=n;i++) if(dep[i]>dep[rz]) rz=i;
	dep[rz]=0;dfs0(rz,0);for(int i=1;i<=n;i++) if(dep[i]>dep[rz]) rz=i;
	for(int d=(dep[rz]+1)>>1;dep[rz]!=d;rz=fa[rz]);
	dep[rz]=0;dfs1(rz,0,1);dfs2(rz,rz);
	for(auto y:g[rz]){
		if(f2[y]>=f2[s1]) s2=s1,s1=y;
		else if(f2[y]>=f2[s2]) s2=y;
	}
	for(auto y:g[rz]){
		int v=(y==s1)?(f2[s2]):(f2[s1]);
		for(int i=dfn[y];i<dfn[y]+siz[y];i++) f1[id[i]]=dep[id[i]]+v;
	}
	build(1,1,n);
	for(int i=1,op,x,y,z;i<=m;i++){
		op=read();
		if(op==1){x=read(),y=read(),z=read();upd(x,y);}
		else{x=read(),z=read();upd(x);}
		printf("%lld\n",solve(z));fflush(stdout);
	}
	return 0;
}

T3

要求的东西可以转化成这样 \(\frac{e(V)}{|V|-1}>lim\) 其中 \(V\) 为选定的点集

移项可以得到 \(e(V)-|V|lim>-lim\) 可以转化成最大权闭合子图的形式

由每条边向他的两个端点连边,源点先边连 \(1\) ,点向汇点连 \(lim\)

发现直接跑网络流可能会什么也不选,于是每次强制选择一个点

这里用到了一个退流的技巧,用网络流跑一遍 \(u->S\) 和 \(T->v\)

把边的流量改成 \(0\) ,最后再跑一遍网络流,就能把 \(u,v\) 这条边带来的影响去掉

Code
#include<bits/stdc++.h>
//#define int long long
#define rint signed
#define inf 0x3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,lim,S,T,ans;
int dis[8010],q[8010],h,t;
int head[8010],HD[8010],ver[40010],edge[40010],to[40010],tot=1;
inline void add(int x,int y,int z){
	ver[++tot]=y;edge[tot]=z;to[tot]=head[x];head[x]=tot;
	ver[++tot]=x;edge[tot]=0;to[tot]=head[y];head[y]=tot;
}
inline bool bfs(){
	for(int i=1;i<=n+m+2;i++) dis[i]=inf;
	dis[S]=0;q[h=t=1]=S;memcpy(head,HD,sizeof(head));
	while(h<=t){
		int x=q[h++];
		for(int i=head[x];i;i=to[i]) if(edge[i]){
			int y=ver[i];
			if(dis[y]>dis[x]+1) dis[y]=dis[x]+1,q[++t]=y;
		}
		if(x==T) return true;
	}
	return false;
}
int dfs(int x,int in){
	if(x==T) return in;
	int res=in,go;
	for(int i=head[x];i;head[x]=i=to[i]) if(edge[i]){
		int y=ver[i];
		if(dis[y]==dis[x]+1){
			go=dfs(y,min(res,edge[i]));
			if(go) edge[i]-=go,edge[i^1]+=go,res-=go;
			else dis[y]=0;
		}
		if(!res) break;
	}
	return in-res;
}
inline int dinic(int s,int t){
	S=s,T=t;int res=0;
	while(bfs()) res+=dfs(S,inf);return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("socialbutterfly.in","r",stdin);
	freopen("socialbutterfly.out","w",stdout);
	n=read(),m=read(),lim=read();S=n+m+1,T=n+m+2;
	for(int i=1,x,y;i<=m;i++){
		x=read(),y=read();
		add(i+n,x,inf),add(i+n,y,inf);
		add(S,i+n,1);
	}
	for(int i=1;i<=n;i++) add(i,T,lim);memcpy(HD,head,sizeof(head));
	for(int i=1;i<=n;i++){
		for(int j=head[i];j;j=to[j]){int y=ver[j];if(y==T){edge[j]=0,edge[j^1]=0;break;}}
		ans-=dinic(i,n+m+1);ans+=dinic(n+m+1,n+m+2);
		if(m-ans>0) puts("Yes"),exit(0);
		for(int j=head[i];j;j=to[j]){int y=ver[j];if(y==T){edge[j]=lim,edge[j^1]=0;break;}}
	}
	puts("No");
	return 0;
}

标签:f2,ch,15,省选,res,rz,int,return,模拟
来源: https://www.cnblogs.com/MaxQAQ/p/15894946.html

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

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

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

ICode9版权所有