P6773 [NOI2020] 命运(dp、线段树合并)

前言

一道看起来很毒瘤但其实还算小清新的题?
理解后感觉其实并没有那么难。
暴力分非常足,好评。
奇妙的线段树合并技巧增加了。

解析

解法1

你是怎么手玩的样例一?
大部分(比如我)都是容斥吧。

把手玩的方法搬到代码上就得到了一个从数据范围来看出题人也很想让我们写的 O(2mpoly)O(2^mpoly)O(2mpoly) 做法。
仔细想想可以树剖线段树维护没有被覆盖的边的个数,dfs的时候顺便修改,时间复杂度 O(2mlog⁡2n)O(2^m\log ^2n)O(2mlog2n)
期望得分 32-40 分。
不太懂为什么网上都是写的 O(2mmlog⁡2n)O(2^mm\log ^2n)O(2mmlog2n)

解法2

你不会真的去写解法1了吧
这个题的形式一看就非常dp。
设计 fx,df_{x,d}fx,d 表示节点 xxx 的子树处理完毕,没有解决的返祖链的祖先的最大深度为 ddd 的方案数。
容易用类似树上背包的形式转移,时间复杂度 O(nmin⁡(n,m))O(n\min(n,m))O(nmin(n,m)),期望得分 646464 分。
然而我写的破玩意做不了完全二叉树,结果就只有 565656 分了(悲)。
(前缀和优化的做法写起来更加好写,而且才能引入后面的正解)

解法3

观察dp转移,发现转移非常有规律,似乎可以维护个线段树之类的东西。
然后垃圾的我根本想不到线段树合并,只能想到重链剖分后每个重链维护个线段树,下标只存子树内有的深度限制(类似于离散化),这样所有线段树的叶子个数之和是 O(nlog⁡n)O(n\log n)O(nlogn),重链处理完后暴力向链头父亲合并,大概是 O(nlog⁡2n)O(n\log^2n)O(nlog2n) 的。
期望得分 88 分。
实现起来非常谔谔,所以只是胡了胡,并没有写。
如果假了的话轻喷(逃


华丽的分割线。
然后我的水平就卡在这个地方了
接下来就是贺题解环节。

解法4

把dp转移写成前缀和形式:
dpx,i=dpx,i′∑j=0depxdps,j+dpx,i′∑j=0idps,j+dps,i∑j=0i−1dpx,jdp_{x,i}=dp'_{x,i}\sum_{j=0}^{dep_x}dp_{s,j}+dp'_{x,i}\sum_{j=0}^{i}dp_{s,j}+dp_{s,i}\sum_{j=0}^{i-1}dp_{x,j}dpx,i=dpx,ij=0depxdps,j+dpx,ij=0idps,j+dps,ij=0i1dpx,j
也就是:
dpx,i=dpx,i′(sums,depx+sums,i)+dps,isumx,i−1dp_{x,i}=dp'_{x,i}(sum_{s,dep_x}+sum_{s,i})+dp_{s,i}sum_{x,i-1}dpx,i=dpx,i(sums,depx+sums,i)+dps,isumx,i1
注意到除了 sums,depxsum_{s,dep_x}sums,depx 是一个常量,其它的东西都与下标密切相关。

考虑线段树合并。
s1=sums,depx+sums,i,s2=sumx,i−1s1=sum_{s,dep_x}+sum_{s,i},s2=sum_{x,i-1}s1=sums,depx+sums,i,s2=sumx,i1
在合并时先递归左子树,在递归右子树,不断更新 s1,s2s1,s2s1,s2 即可。
我觉得你看看代码可能比听我讲更容易理解。

ll s1,s2;
int merge(int x,int y,int l,int r){if(!x&&!y) return 0;else if(!x||!y){if(x){add(s2,tr[x].sum);Mul(x,s1);return x;}else{add(s1,tr[y].sum);Mul(y,s2);return y;}}else if(l==r){int now=New();int a=tr[x].sum,b=tr[y].sum;add(s1,b);tr[now].sum=(s1*a+s2*b)%mod;;add(s2,a);return now;}pushdown(x);pushdown(y);int now=New();  tr[now].ls=merge(tr[x].ls,tr[y].ls,l,mid);tr[now].rs=merge(tr[x].rs,tr[y].rs,mid+1,r);pushup(now);return now;
}

然后这道题就做完啦。
时空复杂度 O(nlog⁡n)O(n\log n)O(nlogn),期望得分 100 分。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("ok\n")
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;
}const int N=5e5+100;
const int inf=1e9+100;
const int mod=998244353;
const bool Flag=0;
#define add(x,y) (((x)+=(y))>=mod&&((x)-=mod))int n,m;#define mid ((l+r)>>1)
struct node{int ls,rs;ll sum,mul=1;
}tr[N*40];
int tot;
vector<int>e[N];
inline int New(){tr[++tot].mul=1;return tot;
}
inline void Mul(int x,int w){if(x){tr[x].sum=tr[x].sum*w%mod;tr[x].mul=tr[x].mul*w%mod;}return;
}
inline void pushdown(int x){if(tr[x].mul!=1){Mul(tr[x].ls,tr[x].mul);Mul(tr[x].rs,tr[x].mul);tr[x].mul=1;}return;  
}
inline void pushup(int k){tr[k].sum=(tr[tr[k].ls].sum+tr[tr[k].rs].sum)%mod;
}
ll ask(int k,int l,int r,int x,int y){if(!k) return 0;if(x<=l&&r<=y) return tr[k].sum;pushdown(k);ll res(0);if(x<=mid) add(res,ask(tr[k].ls,l,mid,x,y));if(y>mid) add(res,ask(tr[k].rs,mid+1,r,x,y));return res;
}
ll s1,s2;
int merge(int x,int y,int l,int r){//if(l>lim) return 0;if(!x&&!y) return 0;else if(!x||!y){if(x){add(s2,tr[x].sum);Mul(x,s1);return x;}else{add(s1,tr[y].sum);Mul(y,s2);//printf("(%d %d) s2=%lld sum=%lld\n",l,r,s2,tr[y].sum);return y;}}else if(l==r){int now=New();int a=tr[x].sum,b=tr[y].sum;add(s1,b);tr[now].sum=(s1*a+s2*b)%mod;;add(s2,a);return now;}pushdown(x);pushdown(y);int now=New();  tr[now].ls=merge(tr[x].ls,tr[y].ls,l,mid);tr[now].rs=merge(tr[x].rs,tr[y].rs,mid+1,r);pushup(now);return now;
}
void ins(int &k,int l,int r,int p){if(!k) k=New();if(l==r){tr[k].sum++;return;}pushdown(k);if(p<=mid) ins(tr[k].ls,l,mid,p);else ins(tr[k].rs,mid+1,r,p);pushup(k);
}
void print(int k,int l,int r){if(!k) return;if(l==r){printf("d=%d dp=%lld\n",l,tr[k].sum);return;}pushdown(k);print(tr[k].ls,l,mid);print(tr[k].rs,mid+1,r);return;
}
int rt[N];int dep[N],d[N];
void init(int x,int fa){dep[x]=dep[fa]+1;for(int to:e[x]){if(to==fa) continue;init(to,x);}return;
}
void dfs(int x,int fa){for(int to:e[x]){if(to==fa) continue;dfs(to,x);}ins(rt[x],0,n,d[x]);for(int to:e[x]){if(to==fa) continue;s1=ask(rt[to],0,n,0,dep[x]);s2=0;rt[x]=merge(rt[x],rt[to],0,n);//printf("----------%d->%d\n",x,to);//print(rt[x],0,n);//puts("");}return;
}signed main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifn=read();for(int i=1;i<n;i++){int x=read(),y=read();e[x].push_back(y);e[y].push_back(x);}init(1,0);m=read();for(int i=1;i<=m;i++){int u=read(),v=read();d[v]=max(d[v],dep[u]);}dfs(1,0);printf("%lld\n",ask(rt[1],0,n,0,0));return 0;
}

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

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

相关文章

ConsurrentDictionary并发字典知多少?

在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理.有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题.https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?redirectedfromMSDN&viewn…

[luogu 4292][bzoj 1758][WC2010] 重建计划(点分治 + dp + 单调队列优化 + 启发式合并)

[WC2010]重建计划problemsolutioncodeproblem 洛谷指路 solution 一看那个道路平均价值的式子&#xff1a;AvgValue∑e∈Sv(e)∣S∣\text{AvgValue}\frac{\sum_{e\in S}v(e)}{|S|}AvgValue∣S∣∑e∈S​v(e)​ 就是 0/1分数规划 的样子。 所以考虑二分最终的答案 midmidmid…

cf1553C. Penalty

cf1553C. Penalty 题意&#xff1a; 有十轮点球&#xff0c;两个队伍轮流进行&#xff0c;1表示进&#xff0c;0表示不进&#xff0c;&#xff1f;表示未知&#xff0c;如果比赛没有了悬念将直接结束。现在让你预测一个情况&#xff0c;使得进行的轮数最少。裁判在决定停止点…

ASP.NET Core 基于JWT的认证(二)

上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍&#xff0c;这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用。.Net Core 2.2Visual Studio 2017ASP.NET Core WebAPI2在上一篇文章中&#xff0c;我们详细的介绍了JWT的知识&#xff0c;这…

P6774 [NOI2020] 时代的眼泪(分块)

前言 看到题目名&#xff1a;别骂了别骂了。 一道很中规中矩的YNOI吧。 卡在整块对整块的贡献上了。 这也确实算是本题最不好做的部分了。 前置知识&#xff1a;Yuno loves sqrt technology I 解析 区间逆序对加强版&#xff1f;很难不想到两道 YLST。 然而多了两维限制&a…

[NOIP2021] 数列(计数dp)

solution f[i][j][k][num][p]:2pf[i][j][k][num][p]:2^pf[i][j][k][num][p]:2p 选择了 iii 个&#xff0c;前 p−1p-1p−1 位 (202p−1)(2^0~2^{p-1})(20 2p−1) 已经选了jjj个&#xff0c;低位向高位进位上来 kkk&#xff0c;前 ppp 位已经确定有 numnumnum 个位置为 111&…

Xor sum HDU - 6955

Xor sum HDU - 6955 题意&#xff1a; 给定一个长度为n的整数序列&#xff0c;求其XOR和不小于k的最短连续子序列。 如果有多个相同长度的连续子序列&#xff0c;则打印具有最小左端点的连续子序列。 如果没有连续的子序列开关XOR总和不小于k&#xff0c;只需打印“-1”。 …

模板:子序列自动机(字符串)

所谓子序列自动机&#xff0c;就是根据子序列建立的自动机。 &#xff08;逃&#xff09; 前言 小清新算法。 解析 和其他自动机类似的&#xff0c;我们希望子序列自动机能且只能接受原串的所有子序列。 考虑一个问题&#xff1a;给你一个串 T&#xff0c;如何判断它是否是…

Docker最全教程之Go实战,墙裂推荐(十九)

前言与其他语言相比&#xff0c;Go非常值得推荐和学习&#xff0c;真香&#xff01;为什么&#xff1f;主要是可以直接编译成机器代码&#xff08;性能优越&#xff0c;体积非常小&#xff0c;可达10来M&#xff0c;见实践教程图片&#xff09;而且设计良好&#xff0c;上手门槛…

[BZOJ3093][Fdu校赛2012] A Famous Game(不等概率)

problem BOZJ3093 solution 逆概率公式&#xff0c;即贝叶斯(Bayes)公式&#xff1a; 假设 B1,B2,...,BnB_1,B_2,...,B_nB1​,B2​,...,Bn​ 是 Ω\OmegaΩ 的一个分割&#xff0c;P(A)>0P(A)>0P(A)>0&#xff0c;则有 P(Bk∣A)P(ABk)P(A)P(Bk)P(A∣Bk)∑i1nP(Bi)…

Mod, Or and Everything HDU - 6950

Mod, Or and Everything HDU - 6950 题意&#xff1a; 给你一个n,问(n%1) or (n%2) or … or (n %n)的值 题解&#xff1a; 无论n为奇偶&#xff0c;定义m(n-1)/2&#xff0c; 我们发现n mod i<m&#xff0c;而当i<m时&#xff0c;有n mod (n-i) i ,于是就有n mod i …

你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗?

在测试一个例子时发现的问题&#xff0c;这个示例实现的功能是刷新页面也能保持表格锁定列的状态&#xff0c;先看下页面的完成效果&#xff1a;测试中发现&#xff0c;几乎相同的代码&#xff1a;在 FineUIMvc&#xff08;Net Framework&#xff09;下没有问题&#xff1a;htt…

模板:拉格朗日乘子法(数学)

所谓拉格朗日乘子法&#xff0c;就是拉格朗日发明的乘子法。 &#xff08;逃&#xff09; 前言 曾经&#xff0c;我被它爆杀&#xff1b;如今&#xff0c;不同的日子&#xff0c;同样的题目&#xff0c;我却不再是曾经的我了。 因为我写模拟退火了。 也不能老是这么混着&…

[UOJ299][CTSC2017] 游戏

【CTSC2017】游戏 problem UOJ299 solution 定义 Xi:X_i:Xi​: 当前已知条件第 iii 局的状态 1/01/01/0&#xff08;胜/败&#xff09;。 将 XiCiX_iC_iXi​Ci​ 记为事件 AiA_iAi​。 假设现在已知条件共有 sss 个&#xff0c;即&#xff1a;第 k1∼sk_{1\sim s}k1∼s​…

Alice and Bob

Alice and Bob 题意&#xff1a; 两人博弈&#xff0c;每次一个人从一堆中拿k个&#xff0c;同时从另一堆拿k * s(s>0)个&#xff0c;问谁先不能拿 10000组数据,N<5000 题解&#xff1a; (x,y)表示第一堆石头数量为x&#xff0c;第二堆为y 如果(x,y)是必败状态&#…

一键发布部署vs插件[AntDeploy]开源了

deploy to remote server by one button click功能支持docker一键部署(支持netcore)支持iis一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚)(支持点火)支持windows服务一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚) 使用插件前我要发布一个net…

CF1257F Make Them Similar(meet in the middle,模拟退火)

前言 sto 退火大师_slb orz sto 正解大师_KHIN orz 只有我啥也不会&#xff0c;哈哈。 有趣的是&#xff0c;两种方法我都想到了一部分&#xff0c;然后都寄掉了。 这有趣个锤子。 解析 Sol1 考虑枚举最终的popcount&#xff0c;然后限制就变成了一个类似于高斯消元的形式…

Find 3-friendly Integers

Find 3-friendly Integers 题意&#xff1a; 定义一个自然数是精妙的&#xff0c;如果他存在一个字串(允许前导0)是3的倍数 问L到R中精妙的数的个数 题解&#xff1a; 数位dp可以做(但我不会。。。) 用结论来做&#xff0c;当n>100时(即为3位数时)必然是精妙的数&#x…

【学习笔记】平等博弈及常见的公平博弈类型

文章目录平等博弈nim堆SG定理nim和常见的公平博弈模型bash博弈nim博弈nim-k博弈wythoff博弈扩展wythoff博弈fibonacci博弈阶梯博弈green hackenbushMisre Nim博弈Every-SGnim积翻棋子游戏游戏的积&#xff0c;tartan定理平等博弈 G{L∣R},LRG\{L|R\},LRG{L∣R},LR&#xff0c;所…

Excel催化剂开源第31波-pdf相关功能实现及类库介绍

在Excel催化剂刚推出的pdf相关功能中&#xff0c;反馈很热烈&#xff0c;不止是用户层面好多人喜欢&#xff0c;也听到在.NET开发群里有询问pdf在winform上展现的功能诉求&#xff0c;一段时间没写开源篇&#xff0c;生怕大家以为Excel催化剂太小气了&#xff0c;不再开发了&am…