ybtoj洛谷P4426:毒瘤(虚树,环套树,暴力)

传送门

解析

顾名思义,十分毒瘤
但有一说一,相对来说这题没有之前做的那两个黑题那么(重读)恶心
而且本题如果放在考场上,暴力枚举非树边的状态dp就可以拿到70分的好成绩(改一改能改到75)

现在考虑正解
注意到,每次暴力枚举非树边的状态进行dp时,状态发生改变的其实来来回回就是少数的几个点而已
所以想到虚树
首先把非树边的端点作为特殊点建出虚树
如何转移呢?
考虑到,两个关键点u,v之间的“连边”是一条有分支的链
不能直接按定义正常转移
但是我们发现,只要这个链的形态不变,dpvdp_vdpv转移到dpudp_udpu系数是不变的
因此,我们可以预先暴力求出这个系数,再进行转移
注意到,所有转移加起来最多把整颗树都搜一遍,复杂度是O(n)O(n)O(n)

还要注意到,由于还有的点不在虚树上,所以关键点的dp初值不是1,还要单独求
这个比较好求,暴力往没有关键点的子树上搜索就行了

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=1e6+100;
const int mod=998244353;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;struct node{int to,nxt;ll k[2][2];
} p1[N<<1],p2[10050];
int fi1[N],cnt1,fi2[N],cnt2;
inline void addline(int x,int y){p1[++cnt1]=(node){y,fi1[x]};fi1[x]=cnt1;return;
}ll dp[N][2];
int op[N],fa[N];
bool jd[N],vis[N];
//op=1:must not be chosen
//op=2:must be chosen
struct edge{int x,y;
} e[50];
int tot;int pos[N],tim;
int pl[N][18],dep[N],siz[N];
void find(int x,int from){vis[x]=1;pos[x]=++tim;for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];siz[x]=1;for(int i=fi1[x]; ~i; i=p1[i].nxt) {if(i==(from^1)) continue;int to=p1[i].to;if(vis[to]) {if(!jd[i]) {jd[i]=jd[i^1]=1;e[++tot]=(edge){x,to};}} else{dep[to]=dep[x]+1;pl[to][0]=x;fa[to]=x;find(to,i);siz[x]+=siz[to];}}//printf("x=%d fa=%d\n",x,fa[x]);return;
}
inline int Lca(int x,int y){if(pos[x]<=pos[y]&&pos[y]<=pos[x]+siz[x]-1) return x;for(int k=17;k>=0;k--){int o=pl[x][k];if(!o||(pos[o]<=pos[y]&&pos[y]<=pos[o]+siz[o]-1)) continue;x=o;}return pl[x][0];
}ll ans;
int tag[N],Top;
void init(int x,int goal,int op){if(x==goal){dp[x][op]=1;dp[x][!op]=0;return;}dp[x][0]=dp[x][1]=1;for(int i=fi1[x];~i;i=p1[i].nxt){int to=p1[i].to;if(to==fa[x]||jd[i]) continue;if(x==Top&&tag[to]!=tim) continue;init(to,goal,op);(dp[x][0]*=(dp[to][0]+dp[to][1]))%=mod; (dp[x][1]*=dp[to][0])%=mod; }return;
}
void Tag(int x,int top){if(fa[x]==top) tag[x]=tim;else Tag(fa[x],top);
}
inline void Addline(int x,int y){p2[++cnt2]=(node){y,fi2[x]};//printf("  add:%d->%d\n",x,y);fi2[x]=cnt2;++tim;Tag(y,x);Top=x;init(x,y,0);p2[cnt2].k[0][0]=dp[x][0];p2[cnt2].k[0][1]=dp[x][1];init(x,y,1);p2[cnt2].k[1][0]=dp[x][0];p2[cnt2].k[1][1]=dp[x][1];//printf("%d->%d k[0][0]=%d k[0][1]=%d k[1][0]=%d k[1][1]=%d\n",x,y,p2[cnt2].k[0][0],p2[cnt2].k[0][1],p2[cnt2].k[1][0],p2[cnt2].k[1][1]);return;
}
void pre(int x){dp[x][0]=dp[x][1]=1;for(int i=fi1[x];~i;i=p1[i].nxt){int to=p1[i].to;if(tag[to]||to==fa[x]||jd[i]) continue;pre(to);(dp[x][0]*=(dp[to][0]+dp[to][1]))%=mod;(dp[x][1]*=dp[to][0])%=mod;}return;
}bool col[N];
bool cmp(int x,int y){return pos[x]<pos[y];
}
int v[N],zhan[N],top;ll ori[N][2];
void dfs(int x,int f){dp[x][0]=ori[x][0];dp[x][1]=ori[x][1];for(int i=fi2[x]; ~i; i=p2[i].nxt) {int to=p2[i].to;if(to==f) continue;dfs(to,x);dp[x][0]=((dp[to][0]*p2[i].k[0][0]%mod+dp[to][1]*p2[i].k[1][0]%mod)%mod*dp[x][0])%mod;dp[x][1]=((dp[to][0]*p2[i].k[0][1]%mod+dp[to][1]*p2[i].k[1][1]%mod)%mod*dp[x][1])%mod;}if(op[x]) {if(op[x]==1) dp[x][1]=0;else dp[x][0]=0;}//printf("  x=%d dp0=%lld dp1=%lld op=%d\n",x,dp[x][0],dp[x][1],op[x]);return;
}
int num;
void solve(int k) {if(k>num){//for(int i=1;i<=n;i++){//printf("  i=%d op=%d\n",i,op[i]);//}dfs(1,0);ll res=dp[1][0]+dp[1][1];ans+=res;ans%=mod;//printf("res=%lld\n\n",res);return;}int a=op[e[k].x],b=op[e[k].y];if(op[e[k].x]!=2){op[e[k].x]=1;//printf("(%d %d)\n",1,2);solve(k+1);op[e[k].x]=a;}if(op[e[k].x]!=1&&op[e[k].y]!=2){op[e[k].x]=2;op[e[k].y]=1;//printf("(%d %d)\n",2,1);solve(k+1);	op[e[k].x]=a;op[e[k].y]=b;}return;
}int main() {
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifmemset(fi1,-1,sizeof(fi1));cnt1=-1;memset(fi2,-1,sizeof(fi2));cnt2=-1;n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read();addline(x,y);addline(y,x);}find(1,-2);num=tot;tot=0;for(int i=1;i<=num;i++){int x=e[i].x,y=e[i].y;if(!col[x]) v[++tot]=x,col[x]=1;if(!col[y]) v[++tot]=y,col[y]=1;}if(!col[1]) v[++tot]=1;sort(v+1,v+1+tot,cmp);zhan[top=1]=v[1];//for(int i=1;i<=tot;i++) printf("%d ",v[i]);putchar('\n');for(int i=2;i<=tot;i++){int x=v[i],lca=Lca(x,zhan[top]);//printf("v[1]=%d x=%d lca=%d\n",v[1],x,lca);while(top>1&&dep[lca]<=dep[zhan[top-1]]){Addline(zhan[top-1],zhan[top]);top--;}if(lca!=zhan[top]){Addline(lca,zhan[top]);zhan[top]=lca;}zhan[++top]=x;//for(int i=1;i<=top;i++) printf("%d ",zhan[i]);putchar('\n');}//printf("ok");while(top>1){Addline(zhan[top-1],zhan[top]);top--;}for(int i=1;i<=n;i++){if(i!=1&&fi2[i]==-1&&!col[i]) continue;int x=i;pre(x);ori[x][0]=dp[x][0];ori[x][1]=dp[x][1];//printf("x=%d ori0=%lld ori1=%lld\n",x,ori[x][0],ori[x][1]);}solve(1);printf("%lld\n",ans);return 0;
}
/*
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软是如何使用 C# 重写 C# 编译器并将其开源的

Roslyn 是 C# 和 Visual Basic.NET 开源编译器的代号。这篇文章将介绍它是如何从微软过去的十年至暗时刻走出来&#xff0c;成为开源跨平台的 C# 和 VB 公共语言引擎。我于 2005 年加入微软&#xff0c;也就是在.NET 2.0 发布之前&#xff0c;当时微软内部已经开始在讨论 Rosly…

P3332 [ZJOI2013]K大数查询(整体二分做法)

P3332 [ZJOI2013]K大数查询 题意: 题解&#xff1a; 利用整体二分来做&#xff0c;这个题和P3834 【模板】可持久化线段树 2的区别在于本题的修改是区间修改&#xff0c;所以将里面的树状数组改成线段树就行&#xff0c;区间修改区间查询 但是不知道为什么我调了一阵子也不对…

[APIO2020]交换城市(交互+kruskal重构树)

[APIO2020]交换城市 description solution 如果u,vu,vu,v存在于一条链上&#xff08;只有两个点度数为111其余点度数为222&#xff09;则无解&#xff0c;否则必有解 如图&#xff0c;不管是哪个点度数>2>2>2&#xff0c;都可以有解 以蓝色为例&#xff0c;第二个…

P3320:寻宝游戏(生成树)

解析 大结论题… 实在是不知道这题和虚树有半毛钱关系吗… 引理 给出一个按照dfs排列的点集S{a1,a2…ak} 它们的极小联通子树的边权和的二倍等于∑dis(a1,a2)dis(a2,a3)...dis(ak−1,ak)dis(ak,a1)\sum dis(a_1,a_2)dis(a_2,a_3)...dis(a_k-1,a_k)dis(a_k,a_1)∑dis(a1​,a2​…

P5333-[JSOI2019]神经网络【dp,容斥】

正题 题目链接:https://www.luogu.com.cn/problem/P5333 题目大意 给出nnn棵树&#xff0c;第iii棵树有kik_iki​个点&#xff0c;每棵树上的每个点和其它树上的所有点都有连边。 求这棵树有多少条哈密顿回路。 答案对998244353998244353998244353取模。 ∑i1nki≤5000\sum…

如何在ASP.NET Core程序启动时运行异步任务(1)

原文&#xff1a;Running async tasks on app startup in ASP.NET Core (Part 1)作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu背景当我们做项目的时候&#xff0c;有时候希望自己的ASP.NET Core应用在启动前执行一些初始化逻辑。例如&#xff0c;你希望验证配置是否合…

扫描线讲解

参考文章&#xff1a; 线段树扫描线&#xff08;有关扫描线的理解&#xff09; 线段树扫描线&#xff08;基本原理&#xff09; 扫描线 第二个文章里面的图很生动&#xff1a; 我总结一下就是&#xff1a;将所给图形的横坐标全部记录&#xff0c;纵坐标记录为扫描线 然后对与…

P5400-[CTS2019]随机立方体【二项式反演,计数】

正题 题目链接:https://www.luogu.com.cn/problem/P5400 题目大意 有一个nmln\times m\times lnml的三维网格&#xff0c;要在每个格子处填上一个数&#xff0c;要求填的数中1∼nml1\sim n\times m\times l1∼nml都恰好出现了一次。 一个极大值被定义为这个格子比其他与它至…

「CEOI2019」魔法树(DP+差分启发式合并)

「CEOI2019」魔法树 description solution 设dpi,j:idp_{i,j}:idpi,j​:i子树在jjj时刻的最大果汁量&#xff0c;显然dpi,jdp_{i,j}dpi,j​在jjj是单调递增的 dpi,jmax⁡(dpi,j,dpi,j−1)dp_{i,j}\max(dp_{i,j},dp_{i,j-1})dpi,j​max(dpi,j​,dpi,j−1​) iii不收获 dpi,j∑…

梁迪:我为MVP骄傲,《微软最有价值专家奖励计划介绍》附专题视频

题记&#xff1a;有些事情&#xff0c;比 MVP 更加不朽&#xff0c;浩气长空&#xff0c;日月星汉&#xff0c;我们为 MVP 和那些心目中的“MVP”感到骄傲。微软 MVP 是一种追求&#xff0c;不必要去强求&#xff0c;但 MVP 必定是俱乐部发展的根基础。火车跑得快全凭车头带&am…

CF1472(div3):总结

文章目录前言A. Cards for Friends题意简述解析代码B. Fair Division题意简述解析代码C. Long Jumps题意简述解析代码D. Even-Odd Game题意简述解析代码E. Correct Placement题意简述解析代码F. New Years Puzzle题意简述解析代码G. Moving to the Capital题意简述解析代码前言…

How Much Memory Your Code Is Using? Gym - 101955J

How Much Memory Your Code Is Using? Gym - 101955J 题意&#xff1a; t组数据&#xff0c;每组数据会有n个定义类型的方式&#xff0c;给你每个类型所占字节&#xff0c;问一共占了多少字节&#xff0c;最终答案按照Kibibyte单位输出&#xff0c;并向上取整 题解&#xf…

P3295 [SCOI2016]萌萌哒(DP+倍增)

P3295 [SCOI2016]萌萌哒 description solution 强制部分区间相同&#xff0c;很容易就想到了并查集&#xff0c;直接暴力并查集合并是O(n2)O(n^2)O(n2)的 只需要考虑那一个数据结构将其转化成O(nlog⁡n)O(n\log n)O(nlogn)的 树之类的就不考虑了&#xff0c;一段一段的区间…

CF1677D-Tokitsukaze and Permutations【结论】

正题 题目链接:https://www.luogu.com.cn/problem/CF1677D 题目大意 对于一个排列pip_ipi​&#xff0c;定义一个序列vF(p)vF(p)vF(p)&#xff0c;其中vi∑j1i−1[pj>pi]v_i\sum_{j1}^{i-1}[p_j>p_i]vi​∑j1i−1​[pj​>pi​]。 一次冒泡排序为依次对1∼n−11\sim…

【恭贺新春】2019年春节放假

2019年放假通知致全体微友&#xff1a; 2019年2月5日&#xff08;正月初一&#xff09;至2月8日&#xff08;正月初四&#xff09;春节放假&#xff0c;共4天&#xff0c;小编停止更新公众号信息。敬请相互转告。值此新春佳节到来之际&#xff0c;“dotNet跨平台”给大家拜个…

模板:圆方树

所谓圆方树&#xff0c;就是又圆又方的树 &#xff08;逃&#xff09; 前言 树有很多良好的性质&#xff0c;也可以上许多算法和数据结构 但我们对于一般图却没有太多办法… 然而&#xff0c;对于有些关注连同性、路径并&交的一般图问题&#xff0c;我们可以用圆方树&…

C - Insertion Sort Gym - 101955C

C - Insertion Sort Gym - 101955C 题意&#xff1a; t组数据&#xff0c;每组数据给你n&#xff0c;k&#xff0c;q&#xff0c;让你求存在多少合法的1~n排列 合法要求&#xff1a; 对排列的前k项进行排序&#xff0c;使得整个序列中最长的递增子序列长度为n-1 题解&#x…

P8330-[ZJOI2022]众数【根号分治】

正题 题目链接:https://www.luogu.com.cn/problem/P8330 题目大意 给出一个长度为nnn的序列aaa&#xff0c;你可以选择其中一个区间将其加上任意整数&#xff0c;要求这个序列的众数出现次数最多。 输出最多次数和可能的众数。 1≤n≤2105,1≤ai≤109,∑n≤51051\leq n\leq …

华为云.NET Core支持情况调查

各大公有云都提供了开发者开发的SDK&#xff0c;今天我们来看看华为云对.NET Core的支持情况怎么样&#xff1f; .NET SDK地址 https://developer.huaweicloud.com/sdk#.NET华为云的.NET SDK相比其他语言少的可伶&#xff0c;而且这几个SDK还不支持.NET Core。SDK的支持实在太差…

[2021-07-19 内测NOIP] 操作(状压DP),异或(字典树),等级(线段树),矩阵(DP)

[2021-07-19 内测] NOIP操作descriptionsolutioncode异或descriptionsolutioncode等级descriptionsolutioncode矩阵descriptionsolutioncode操作 description 有n堆石子&#xff0c;每堆石子都有一定的数量&#xff0c;第i堆石子的数量用Ai表示。 任意两堆石子均可合并&…