冲刺省选2月14日第十五场


T1 开心消消乐

对于已经确定的 0/1 序列,考虑将操作转化使得可以增量构造

将每两个球看作 1 组,开一个栈保存前缀

此时要将当前组 (a,b) 加入栈中,只有两个操作

  1. 将 a,b 依次压入栈中
  2. 将 a 压入栈中并将栈中元素合并,然后将 b 压入栈中

使用一个函数 \(G[a,b](x)\) 保存这个栈,表示加入 0 返回 a,加入 1 返回 b

压栈操作转化为将 \(G[a,b](x)\) 改变为 \(G[a',b'](x)\)

所以就有了一个 dp,\(f_{i,j0,j1}\) 表示前 i 组是否能构成函数 \(G[j0,j1](x)\)

对于计数问题,dp套dp,\(f_{i,j}\)表示前 j 组恰好能构成的函数集合为 i 的方案数,复杂度 \(O(2^{2^2}n)\)

T2 树上的棋局

对于一棵有根树,一个节点的 SG 是其子树内到它的最远距离,一个棋子的 SG 是所在节点的 SG,一棵树的 SG 是所有棋子的异或和

考虑换根对节点 SG 的影响,设可重集合 \(dis_x\) 为以 x 为根时每个儿子的子树内最大深度的集合

然后发现集合内可能有贡献的只有最大值 (记为 \(f_x\)) 和次大值 (记为 \(g_x\)),因为 以 y 为根的 x 的子树就是整个联通块减去以 x 为根时 y 所在的子树,即每个节点最多只会有一个出点不能选

然后考虑 \(f_x,g_x\) 分别何时有贡献,当 x 为根时,最远点一定是直径的一个端点,且这条路径一定过树的中心(直径的中点)

当中心 md 为根时,所有点取 \(g_x\),当 y 为根时,\(y->md\) 路径上所有点取 \(f_x\),其他取 \(g_x\)

考虑到 \(f,g\) 交换和奇偶性改变对权值的影响,可以在线段树上维护 \(2* 2\) 的矩阵并支持行交换和列交换,然后链加和子树加就树剖+线段树就行了

(直径没中点?在中间硬塞一个)

T3 社会黄油飞

还没写,等填网络流的坑的时候再说吧,,,

这个数据就比较离谱,因为他大样例不知道用了什么方法构造了一下,我觉得他懒得多构造几种图了,然后他确实只有随的图和大样例的那种图

代码

T1

#include
#include
#include
#include
using namespace std;
#define il inline
#define int long long
const int N=1e5+11;
const int mod=998244353;
struct sta_{bool a,b;}sta[4];
char pot[N],tx[N];
int n;
int rle[2][2];
int st[N];
int f[16][N];
il void md(int &x){if(x>=mod)x-=mod;}
bool jud(int i,char b){return tx[i]==b;}
bool judi(int i,char j){return jud(i,'?')||jud(i,j);}
int mrg(int i,int j,int k){return (k<<2)+(j<<1)+i;}
bool get_ab(bool jd,int id){return !jd?sta[id].a:sta[id].b;}
il int read(){
	int s=0;char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
int opt1(int id,int a,int b){
	bool jd0=st[mrg(a,b,0)],jd1=st[mrg(a,b,1)];
	jd0=get_ab(jd0,id);jd1=get_ab(jd1,id);
	return rle[jd0][jd1];
}
int opt2(int id,int a,int b){
	bool jd0=st[mrg(get_ab(a,id),b,0)],jd1=st[mrg(get_ab(a,id),b,1)];
	return rle[jd0][jd1];
}
signed main(){
	freopen("game.in","r",stdin);freopen("game.out","w",stdout);
	for(int i=0;i<4;++i)sta[i]={(bool)(i&2),(bool)(i&1)},rle[sta[i].a][sta[i].b]=i;
	int t=read();while(t--){
		memset(f,0,sizeof(f));
		scanf("%s",pot+1);scanf("%s",tx+1);n=strlen(tx+1);
		for(int i=0;i<8;++i)st[i]=pot[i+1]-'0';
		for(int i=0;i<2;++i)for(int j=0;j<2;++j){
			if(!judi(1,i+'0')||!judi(2,j+'0'))continue;
			++f[1<

T2

#include
#include
#include
#include
#include
#include
using namespace std;
#define il inline
const int N=2e5+11;
int n,m,md;
int rt[2],now,ds;
int pg[N],sta[N],p;
int dfn[N],rle[N],tot;
int mxp[N],mxd[N],cmxd[N];
int top[N],son[N],f[N],siz[N],dep[N];
int st[20][N];
vectorvct[N];
vector::iterator it;
il int max_(int x,int y){return x>y?x:y;}
bool cmp(int a,int b){return mxd[a]>mxd[b];}
struct mat_{
	bool c,r;
	int a[2][2];mat_(){}
	mat_(bool c_,bool r_,int a_[]){c=c_,r=r_;memcpy(a,a_,sizeof(a_));}
	void revr(){swap(a[0][0],a[1][0]);swap(a[0][1],a[1][1]);r^=1;}
	void revc(){swap(a[0][0],a[0][1]);swap(a[1][0],a[1][1]);c^=1;}
	friend mat_ operator^(mat_ a,mat_ b){
		a.c=a.r=0;
		a.a[0][0]^=b.a[0][0];
		a.a[0][1]^=b.a[0][1];
		a.a[1][0]^=b.a[1][0];
		a.a[1][1]^=b.a[1][1];
		return a;
	}
}tre[N*4];
il int read(){
	int s=0;char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
void dfs1(int x,int fa){
	for(int i=1;i<=pg[dep[x]];++i)st[i][x]=st[i-1][st[i-1][x]];
	siz[x]=1;for(int v : vct[x]){
		if(v==fa)continue;
		dep[v]=dep[st[0][v]=f[v]=x]+1;
		dfs1(v,x);siz[x]+=siz[v];
		if(siz[son[x]]mxd[x])cmxd[x]=mxd[x],mxd[x]=mxd[v];
		else if(mxd[v]==mxd[x])cmxd[x]=mxd[v];
		else if(mxd[v]cmxd[x])cmxd[x]=mxd[v];
	}
}
void get_out(int x,int fa,int dis){
	vector s;mxp[x]=dis;
	for(int v : vct[x])if(v!=fa)s.push_back(v);
	sort(s.begin(),s.end(),cmp);
	if(!s.size())return;
	if(s.size()==1){get_out(s[0],x,dis+1);return;}
	for(int v : s)get_out(v,x,max_(dis+1,(v==s[0]?mxd[s[1]]:mxd[s[0]])+2));
}
void get_rt(int x,int fa,int dis){
	if(dis>ds)ds=dis,now=x;
	for(int v : vct[x]){
		if(v==fa)continue;
		get_rt(v,x,dis+1);
	}
}
void get_sta(){
	int x=rt[0],y=rt[1];
	if(dep[x]sx,sy;
	while(dep[x]>dep[y])sx.push_back(x),x=f[x];
	while(x!=y){
		sx.push_back(x),sy.push_back(y);
		x=f[x],y=f[y];
	}sx.push_back(x);
	for(int i=sy.size()-1;i>=0;--i)sx.push_back(sy[i]);
	for(int i=0;idep[y]?y:x;
}
il void upd(int i){
	if((i<<1)>8e5)return;
	tre[i]=tre[i<<1]^tre[i<<1|1];
}
void build(int i,int l,int r){
	if(l==r){
		tre[i].a[0][0]=cmxd[rle[l]];
		tre[i].a[1][0]=mxd[rle[l]];
		return;
	}int mid=(l+r)>>1;
	build(i<<1,l,mid);build(i<<1|1,mid+1,r);upd(i);
}
il void pushdown(int i){
	if((i<<1)>8e5)return;
	if(tre[i].r)tre[i<<1].revr(),tre[i<<1|1].revr();
	if(tre[i].c)tre[i<<1].revc(),tre[i<<1|1].revc();
	tre[i].r=tre[i].c=0;
}
void chg(int i,int l,int r,int L,int R,bool jd){
	if(L>R)return;pushdown(i);
	if(l>=L&&r<=R){
		if(jd)tre[i].revc();
		else tre[i].revr();
		return;
	}int mid=(l+r)>>1;
	if(L<=mid)chg(i<<1,l,mid,L,R,jd);
	if(R>mid)chg(i<<1|1,mid+1,r,L,R,jd);upd(i);
}
void tre_rev(int x,int y,bool jd){
	int fx=top[x],fy=top[y];
	while(fx!=fy){
		if(dep[fx]