【学习笔记】[省选联考 2023] 填数游戏

news/2024/11/29 9:55:56/

我不好说,因为考场上我想成二分图然后就gg了

这题不难,真的不难。

∣Ti∣≤2|T_i|\le 2Ti2这个性质一看就非常亲切啊,可以看成一条aia_iaibib_ibi的连边,不妨将问题做一些泛化,将∣Ti∣=1|T_i|=1Ti=1看成连向aia_iai的自环。

那么对于一个连通块显然边的数目不超过点的数目,让我们先讨论一些比较简单的情形。

如果基环树且基环为自环,那么选择方式唯一,简单算一下即可。

如果基环树且基环不为自环,那么基环外选择方式唯一,基环内有两种方式,简单贪心一下应该不难得出答案。

如果为树,假设{ai}\{a_i\}{ai}已经确定了,不妨看成是以uuu为根并且完成定向的一颗有根树,Bob\text{Bob}Bob可以将vvv到根节点的路径上的边反向,那么相当于每个点存了一个答案,初始所有点答案都为000Bob\text{Bob}Bob会选择答案最小的那个点。然后Alice\text{Alice}Alice依次加入每条边,对于没有别固定的边(u,v)(u,v)(u,v),设uuuvvv的父亲,如果选vvv相当于vvv子树外的点答案+1+1+1,如果选uuu相当于vvv子树内的点答案+1+1+1(称为不动点),如果有两个点u,vu,vu,v都是翻转点,那么显然u,vu,vu,v满足祖先关系(否则不优),而显然选深度小的点作为不动点更优,那么就做完了。

复杂度O(nlog⁡n)O(n\log n)O(nlogn)

总之是非常套路的题,但是不知道为啥考场上没想出来。

总之就是非常难写,今年省选代码量确实有一点点大

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define db double
#define fi first
#define se second
using namespace std;
const int N=1e6+5;
int T,n,m,fa[N],sz1[N],sz2[N],a[N][2],b[N][2];
int rt,re,pre[N],prepos[N],visit[N],task,res,dfn[N],num,home[N],cntnode;
int head[N*2],nxt[N*2],to[N*2],pos[N*2],tot;
int posedge;
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
struct node{int dat,min;
}t[N<<2];
void Add(int p,int x){t[p].min+=x,t[p].dat+=x;
}
void pushup(int p){t[p].min=min(t[p<<1].min,t[p<<1|1].min);
}
void pushdown(int p){if(t[p].dat){Add(p<<1,t[p].dat),Add(p<<1|1,t[p].dat);t[p].dat=0;}
}
void upd(int p,int l,int r,int ql,int qr,int x){if(ql<=l&&r<=qr){Add(p,x);return;}int mid=l+r>>1;pushdown(p);if(ql<=mid)upd(p<<1,l,mid,ql,qr,x);if(mid<qr)upd(p<<1|1,mid+1,r,ql,qr,x);pushup(p);
}
int qry(int p,int l,int r,int ql,int qr){if(ql<=l&&r<=qr)return t[p].min;int mid=l+r>>1;pushdown(p);if(qr<=mid)return qry(p<<1,l,mid,ql,qr);if(mid<ql)return qry(p<<1|1,mid+1,r,ql,qr);return min(qry(p<<1,l,mid,ql,qr),qry(p<<1|1,mid+1,r,ql,qr));
}
void add(int x,int y,int z){to[++tot]=y,pos[tot]=z,nxt[tot]=head[x],head[x]=tot;to[++tot]=x,pos[tot]=z,nxt[tot]=head[y],head[y]=tot;
}
void unionset(int x,int y){int u=find(x),v=find(y);if(u!=v)fa[u]=v,sz1[v]+=sz1[u]+1,sz2[v]+=sz2[u];else sz1[v]++;
}
int calc(int pos,int v){assert(v);return a[pos][0]==v||a[pos][1]==v;
}
int X,Y,Z;
int check(int pos){return a[pos][0]==b[pos][0]&&a[pos][1]==b[pos][1]||a[pos][0]==b[pos][1]&&a[pos][1]==b[pos][0];
}
//fixed
void findroot(int u,int topf){visit[u]=task;for(int k=head[u];k;k=nxt[k]){if(k!=(topf^1)){int v=to[k];if(visit[v]!=task)findroot(v,k);else {rt=u;if(u==v)posedge=pos[k];}}}
}
//fixed
void dfs(int u,int topf){visit[u]=task;for(int k=head[u];k;k=nxt[k]){int v=to[k];if(k!=(topf^1)){if(visit[v]!=task){pre[v]=u,prepos[v]=pos[k],dfs(v,k);res+=calc(pos[k],v);}else if(u!=rt){assert(!re);re=u;if(check(pos[k])){Z++;}else {if(calc(pos[k],rt))X++;else if(calc(pos[k],re))Y++;}}}}
}
int solve1(int u){rt=u,re=0,task++;X=0,Y=0,Z=0,res=0,posedge=0;findroot(rt,0);if(posedge)res+=calc(posedge,rt);task++;dfs(rt,0);if(!re)return res;assert(rt!=re);while(re!=rt){int tmp=prepos[re];res-=calc(tmp,re);if(check(tmp)){Z++;}else{if(calc(tmp,re))X++;else if(calc(tmp,pre[re]))Y++;}re=pre[re];}if(X>Y)swap(X,Y);if(X+Z<=Y)return X+Z+res;return (X+Y+Z)/2+res;
}
void modify(int u,int state,int f){if(state==0){upd(1,1,m,dfn[u],dfn[u]+home[u]-1,f);}else{upd(1,1,m,dfn[u],dfn[u]+home[u]-1,-f);upd(1,1,m,1,cntnode,f);}
}
void dfs1(int u,int topf){dfn[u]=++num,home[u]=1,cntnode++;for(int k=head[u];k;k=nxt[k]){int v=to[k];if(v!=topf){dfs1(v,u),home[u]+=home[v];}}
}
void dfs2(int u,int topf,int f){for(int k=head[u];k;k=nxt[k]){int v=to[k];if(v!=topf){if(check(pos[k])){modify(v,1,f);}else if(calc(pos[k],v)){modify(v,1,f);}else if(calc(pos[k],u)){modify(v,0,f);}dfs2(v,u,f);}}
}
void dfs3(int u,int topf){res=max(res,qry(1,1,m,1,cntnode));for(int k=head[u];k;k=nxt[k]){int v=to[k];if(v!=topf){if(check(pos[k])){modify(v,1,-1);modify(v,0,1);}dfs3(v,u);if(check(pos[k])){modify(v,1,1);modify(v,0,-1);}}}
}
int solve2(int u){num=0,cntnode=0,dfs1(u,0);assert(cntnode==sz2[find(u)]);res=0;dfs2(u,0,1),dfs3(u,0),dfs2(u,0,-1);assert(t[1].min==0);return res;
}
int solve(){int tot=0;for(int i=1;i<=m;i++){if(find(i)==i){if(sz1[i]>sz2[i]){return -1;}if(sz1[i]==sz2[i])tot+=solve1(i);else tot+=solve2(i);}}return tot;
}
int main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>T;while(T--){cin>>n>>m;tot=1;for(int i=1;i<=m;i++)head[i]=0;for(int i=1;i<=m;i++)fa[i]=i,sz1[i]=0,sz2[i]=1;for(int i=1;i<=n;i++)a[i][0]=a[i][1]=b[i][0]=b[i][1]=0;for(int i=1;i<=n;i++){int k;cin>>k;while(k--)cin>>a[i][k];}for(int i=1;i<=n;i++){int k;cin>>k;if(k==2){while(k--)cin>>b[i][k];unionset(b[i][0],b[i][1]);add(b[i][0],b[i][1],i);}else{while(k--)cin>>b[i][k];unionset(b[i][0],b[i][0]);add(b[i][0],b[i][0],i);}}cout<<solve()<<"\n";}
}

http://www.ppmy.cn/news/41704.html

相关文章

【计算机系统结构】第三章 流水线技术

文章目录第三章 流水线技术3.1 先行控制技术3.2 流水线的基本概念3.3 流水操作中的相关第三章 流水线技术 提高计算机性能 缩短 CPI&#xff1a;RISC技术提高指令并行度&#xff1a;流水线技术 3.1 先行控制技术 指令重叠执行 指令执行时间&#xff1a;Tit取指令t分析t执行…

如何开启全新旅途,实现旅游市场活力复苏

2023年&#xff0c;随着疫情逐渐得到控制&#xff0c;旅游业迎来了新的发展机遇&#xff0c;如何重振旅游市场成为了各界关注的焦点。那么&#xff0c;我们该如何开启全新的旅途&#xff0c;实现旅游市场活力的复苏呢&#xff1f; 增强服务意识&#xff0c;助力旅游市场活力复苏…

Java语言-----泛型的认识

目录 一.什么是泛型 二.泛型类的使用 2.1泛型类的定义 2.2泛型类的数组使用 三.泛型的上界 四.泛型的方法 五.泛型与集合 &#x1f63d;个人主页&#xff1a; tq02的博客_CSDN博客-C语言,Java领域博主 &#x1f308;梦的目标&#xff1a;努力学习&#xff0c;向Java进发…

Python 进阶指南(编程轻松进阶):十三、性能测量和大 O 算法分析

原文&#xff1a;http://inventwithpython.com/beyond/chapter13.html 对于大多数小程序来说&#xff0c;性能并不那么重要。我们可能会花一个小时编写一个脚本来自动执行一个只需要几秒钟就能运行的任务。即使需要更长的时间&#xff0c;当我们端着一杯咖啡回到办公桌时&#…

Servlet入门讲解

文章目录简介快速入门执行流程生命周期方法介绍体系结构urlPattern配置XML配置简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。 使用Servlet就可以实现&#xff0c;根据不同的登录用户在页面上动态显示不同内容。 Servlet是JavaEE规…

Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCVSharp实现图像的伽马变换算法增强(C#)

Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCVSharp实现图像的拉普拉斯算法增强&#xff08;C#&#xff09;Baumer工业相机Baumer工业相机使用图像算法增加图像的技术背景Baumer工业相机通过BGAPI SDK联合OpenCV使用图像增强算法1.引用合适的类文件2.BGAPI SDK在图像回调…

SpringCloud微服务技术栈之网关服务Gateway

文章目录SpringCloud微服务技术栈之网关服务Gateway前言网关服务Gateway的基本概念Gateway的体系结构Gateway的主要功能网关服务Gateway的架构设计架构设计方案示例代码网关服务Gateway的实践操作1. 创建工程2. 配置路由规则3. 实现过滤器4. 集成服务注册中心5. 启动网关服务器…

面试题

用 C写一个函数&#xff0c;交换两个整型变量 int a 5, b 10; cout << "Before swapping: a " << a << ", b " << b << endl; swapVars<int>(a, b); cout << "After swapping: a " << a …