社区讨论
蒟蒻刚学OI,求助大佬
P3642[APIO2016] 烟花表演参与者 27已保存回复 28
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 28 条
- 当前快照
- 1 份
- 快照标识符
- @mi6xw4f3
- 此快照首次捕获于
- 2025/11/20 12:36 4 个月前
- 此快照最后确认于
- 2025/11/20 16:23 4 个月前
WA 40 不知道为什么。
思路和题解有所不同,但都是DP。
考虑 表示节点 子树中叶子深度改为 的最小代价。
是一个连续的下凸函数,且由斜率为整数的一次函数拼接而成。
考虑 从 转移,这里 是 的儿子。
,这里 表示 到 的导火索长度。
可以发现其中 的部分关于自变量 是一个形如:
的函数。
其中 只与 中斜率为 的一段有关。
故对于任意的 ,只需记录它的斜率为 的一段的端点和函数值即可。
也就是结构体
Dat 中的 x, y, z 三个变量。在 中,需要将若干个形如上述的函数合并,并求出斜率为 的一段。请参见代码。
CPP#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
int N,M;
int h[600005],nxt[600005],to[600005],tot; LL w[600005];
void ins(int x,int y,LL z){nxt[++tot]=h[x];to[tot]=y;w[tot]=z;h[x]=tot;}
struct Dat{
LL x,y,z;
Dat(LL x=0,LL y=0,LL z=0):x(x),y(y),z(z){}
}f[600005],st[600005];
Dat operator+(Dat p1,LL p2){
return Dat(p1.x+p2,p1.y+p2,p1.z);
}
LL v[600005]; int t;
int main(){
scanf("%d%d",&N,&M);
for(int i=2;i<=N+M;++i){
int x; LL y;
scanf("%d%lld",&x,&y);
ins(x,i,y);
}
for(int i=N;i>=1;--i){
t=0;
for(int j=h[i];j;j=nxt[j]){
st[++t]=f[to[j]]+w[j];
v[2*t-1]=st[t].x;
v[2*t]=st[t].y;
}
sort(v+1,v+t+t+1);
f[i].x=v[t], f[i].y=v[t+1];
for(int j=1;j<=t;++j){
if(v[t]<st[j].x) f[i].z+=st[j].z+st[j].x-v[t];
else if(v[t]>st[j].y) f[i].z+=st[j].z+v[t]-st[j].y;
else f[i].z+=st[j].z;
}
}
printf("%lld\n",f[1].z);
return 0;
}
回复
共 28 条回复,欢迎继续交流。
正在加载回复...