当前位置: 首页 > news >正文

OIFC 2026省选 0120

胜兵必骄 wars

\(a=1\) 为黑色,否则为白色。

注意到一次战斗本质是交换颜色,一条边被操作两次不会对颜色产生影响。最初的想法是找到一个黑点 \(u\),与白色儿子交换颜色,递归到子树处理;同色的儿子提前递归,回溯时趁 \(u\) 还没从白色变回黑色时连做两次。

这样会有一些问题,如果一个点的所有儿子都与他同色,那么这个点必须得被提前反色。设 \(f_{u,0/1}\) 表示 \(u\) 颜色为 \(0/1\) 时能否被操作以及此时的构造。从一个有不同色相邻点的点开始 dfs,做树上 DP 即可。

证明一下为什么两种颜色点均存在时一定有解,找到树上一条两端不同色的边,分成两个子问题,如果某一侧颜色全相同,在当前边两次操作之间做,否则在操作之前做,一定有解。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
typedef pair<ll,ll> pll;
template<typename T>
void chkmin(T &x,const T &y){x=min(x,y);}
template<typename T>
void chkmax(T &x,const T &y){x=max(x,y);}
const int inf=0x3f3f3f3f;
const ll infll=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
void add(int &x,int y){x+=y;if(x>=MOD) x-=MOD;
}
int qpow(int a,ll b){int mul=1;while(b){if(b&1) mul=(ll)mul*a%MOD;a=(ll)a*a%MOD;b>>=1;}return mul;
}
const int N=1000005;
int n,a[N],f[N][2],vis[N];
vector<int> G[N];
vector<pii> vec[N][2];
void dfs(int u,int fa){int cnt[2];cnt[0]=cnt[1]=0;for(auto v:G[u]){if(v==fa) continue;dfs(v,u);cnt[a[v]]++;}if(cnt[0]+cnt[1]==0){f[u][0]=f[u][1]=1;return;}for(int c=0;c<2;c++){if(cnt[c^1]){f[u][c]=1;for(auto v:G[u]){if(v==fa) continue;if(f[v][a[v]]) vec[u][c].push_back({-1,v});}for(auto v:G[u]){if(v==fa) continue;if(a[v]^c){vec[u][c].push_back({u,v});if(!f[v][a[v]]) vec[u][c].push_back({-1,v});vec[u][c].push_back({u,v});}}int vv=vec[u][c].back().second;vec[u][c].pop_back();for(auto v:G[u]){if(v==fa) continue;if(!(a[v]^c)){vec[u][c].push_back({u,v});if(!f[v][a[v]]) vec[u][c].push_back({-1,v});vec[u][c].push_back({u,v});}}vec[u][c].push_back({u,vv});}else f[u][c]=0;}
}
void dfs2(int u,int c){for(auto [x,y]:vec[u][c]){if(x==-1) dfs2(y,a[y]);else printf("%d %d\n",x,y),a[y]^=1;}
}
void __INIT__(){}
void __SOLVE__(){scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);G[u].push_back(v),G[v].push_back(u);}for(int i=1;i<=n;i++){bool flag=false;for(auto j:G[i]) if(a[i]!=a[j]){flag=true;break;}if(flag){dfs(i,i);dfs2(i,a[i]);return;}}
}
int main(){#ifndef JZQfreopen("wars.in","r",stdin);freopen("wars.out","w",stdout);#endifint T=1;// scanf("%d",&T);__INIT__();while(T--) __SOLVE__();return 0;
}

数据恢复 recovery

观察性质

考虑做判定。

*观察 1

对于非前缀最大值且不固定的位置,其目标顺序应递增。

否则,可以调整出字典序更小的方案。

观察 2

对于一个前缀最大值位置 \(i\),设 \(mx_i=\max\limits_{\substack{pre_i\le j<nxt_i \\ i\neq j}}\{a'_j\}\),则 \(i\) 不能被替换当且仅当 \((mx_i,a'_i]\) 中的数被固定。

笔者考场仅观察到了更弱的结论(必要不充分条件)。

必要性显然,直接调整。

充分性证明,从左往右固定每一个前缀最大值,如果 \(i\) 被替换,则 \(i\) 被移至 \(nxt_i\) 后,必然有一个 \(nxt_i\) 后的数要移进 \(i\sim nxt_i\),根据观察 1,这就会导致产生新的前缀最大值。


综上,一个方案合法当且仅当不被固定的非前缀最大值递增,不被固定的前缀最大值满足 \((mx_i,a'_i]\) 被固定。

考虑在值域上 DP,设 \(f_i\) 表示考虑了 \(1\sim i\) 的非前缀最大值,且 \(i\) 不被固定的方案数。

暴力的转移为:

\[f_i=\sum_{\substack{j<i \\ p_j<p_i}}f_j2^{cnt_{j+1,i-1}},\ c_{p_i}=0 \]

其中 \(cnt_{l,r}\) 表示被 \([l,r]\) 完全包含的 \((mx_i,a'_i]\) 数量。

用前缀和维护 \(cnt\),用树状数组维护 \(f\),即可 \(\mathcal{O}(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
typedef pair<ll,ll> pll;
template<typename T>
void chkmin(T &x,const T &y){x=min(x,y);}
template<typename T>
void chkmax(T &x,const T &y){x=max(x,y);}
const int inf=0x3f3f3f3f;
const ll infll=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353,INV2=(MOD+1)>>1;
void add(int &x,int y){x+=y;if(x>=MOD) x-=MOD;
}
int qpow(int a,ll b){int mul=1;while(b){if(b&1) mul=(ll)mul*a%MOD;a=(ll)a*a%MOD;b>>=1;}return mul;
}
const int N=1000005;
int n,a[N],p[N],nxt[N],c[N],pre[N],cnt[N],pw[N],invpw[N];
int val[N],tr[N],f[N];
#define lowbit(x) ((x)&(-(x)))
void modify(int x,int v){add(val[x],v);for(;x<=n+1;x+=lowbit(x)) add(tr[x],v);
}
void change(int x,int v){int d=v-val[x];if(d<0) d+=MOD;modify(x,d);
}
int query(int x){int sum=0;for(;x;x-=lowbit(x)) add(sum,tr[x]);return sum;
}
int query(int l,int r){int s=query(r)-query(l-1);if(s<0) s+=MOD;return s;
}
void __INIT__(){pw[0]=invpw[0]=1;for(int i=1;i<N;i++){pw[i]=(pw[i-1]<<1)%MOD;invpw[i]=(ll)INV2*invpw[i-1]%MOD;}
}
void __SOLVE__(){scanf("%d",&n);int mx=0,lst=0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);p[a[i]]=i;if(a[i]>mx){nxt[lst]=i,pre[i]=lst;mx=a[i],lst=i,c[i]=1;}else c[i]=0;}nxt[lst]=n+1;vector<pii> vec;a[0]=0;for(int i=1;i<=n;i++){if(!c[i]) continue;int mx=a[pre[i]];for(int j=i+1;j<nxt[i];j++) chkmax(mx,a[j]);vec.push_back({mx+1,a[i]});}for(int i=1;i<=n;i++) cnt[i]=0;for(int i=1,j=0;i<=n;i++){if(i>vec[j].second) j++;if(j<vec.size()&&i==vec[j].first) cnt[i]=1;cnt[i]+=cnt[i-1];if(j>=vec.size()||i<vec[j].first) pre[i]=i;else pre[i]=vec[j].first-1;}// for(int i=1;i<=n;i++) printf("%d ",cnt[i]);// printf("\n");for(int i=1;i<=n+1;i++) val[i]=tr[i]=0;modify(1,1);for(int i=1,j=0;i<=n;i++){if(j<vec.size()&&i>vec[j].second){for(int k=vec[j].first;k<=vec[j].second;k++) change(p[k]+1,(ll)INV2*val[p[k]+1]%MOD);j++;}if(c[p[i]]) continue;f[i]=(ll)pw[cnt[pre[i]]]*query(p[i]+1)%MOD;modify(p[i]+1,(ll)invpw[cnt[pre[i]]]*f[i]%MOD);}// for(int i=1;i<=n;i++) printf("%d ",f[i]);// printf("\n");printf("%lld\n",(ll)pw[vec.size()]*query(n+1)%MOD);
}
int main(){#ifndef JZQfreopen("recovery.in","r",stdin);freopen("recovery.out","w",stdout);#endifint T=1;scanf("%*d%d",&T);__INIT__();while(T--) __SOLVE__();return 0;
}
http://www.jsqmd.com/news/275344/

相关文章:

  • 流量累计程序 博途v15编写的西门子流量累计程序,封装好的FB块直接可以拿来用,并且配有视频解说
  • qt之实现截图效果
  • 2026年广东比较好的刀塔机定制需要多少钱,Y轴/尾顶机/排刀机/数控4+4/正交Y/动力刀塔/直Y,刀塔机厂家推荐排行
  • 【毕业设计】springboot基于大数据技术的诗词信息系统(源码+文档+远程调试,全bao定制等)
  • 【Python】解决 Windows 下 pip 安装报错 OSError: [Errno 2] No such file or directory (路径过长问题)
  • 深夜调模型的工程师都懂,燃油车和电动车之间总得有个“和事佬“——增程器。今天咱们聊的这个Cruise仿真模型,就是要把这个中间商做出价值
  • 《把脉行业与技术趋势》-72-伟大的组织,不只是会收割,更要会培育土壤。“春天开荒播种是为了秋天收获果实”。
  • 【python实用小脚本-336】HR如何用Python改造敏感信息传递流程?信息安全×代码的化学反应,轻松实现音频隐写术
  • 【2026开年巨献】Gemini 3.0全面解析:从技术原理到商业落地,开发者不可错过的AI革命指南
  • 【GoFrame (GF) 】高性能、模块化、企业级的 Go 语言开发框架
  • 【计算机毕业设计案例】基于springboot+大数据技术旅游商品管理系统大数据毕设选题推荐:基于大数据技术旅游商品管理系统基于springboot+大数据技术旅游商品管理系(程序+文档+讲解+定制)
  • 【2026 深度观察】大模型战国时代:中美双极、四强争霸与生态分化
  • 同步FIFO的三种写法各有特点。计数器法直接用读写计数器差值判断空满,适合小深度场景。举个例子,当depth=1时可以直接用寄存器存储数据
  • 大数据领域 Elasticsearch 集群搭建全流程
  • 自动聊天工具尝试一(寻找方向)
  • 一个python笔试题及扩展
  • 支持付费内容与广告的社区论坛小程序商业化运营源码系统
  • 2025年最受物流企业青睐的自动化立体库解决方案TOP 5,贯通式货架/中型货架/平台货架/轻型货架/重型货架自动化立体库公司有哪些
  • 永久关闭windows系统的自动更新的6种方法 详细介绍
  • 详细介绍:PHP 8.0到PHP 8.5各版本主要新特性的整理
  • 盘点2026年EOR名义雇主服务优势,教你如何选择EOR名义雇主高效产品推荐
  • 猎奇榜
  • Product Hunt 每日热榜 | 2026-01-20
  • 经营范围填写指南
  • 通达信【万马奔腾V8】主图与选股指标源码分享
  • 和vvv
  • Python 中subprocess.getstatusoutput(cmd) 函数注入命令风险分析
  • ARM嵌入式开发代码实践——LED灯闪烁(C语言版)
  • 突破想象!AI应用架构师用科研AI智能体重塑金融学分析格局
  • Qt的技巧笔记(二):ComboBox 下拉组合框组件