洛谷

Codeforces


这是一个非正解,被正解暴踩,但它还是过了。


思路

首先很容易想到DP。

设\(dp_{x,i}\)表示\(x\)子树全部被覆盖,而且向上恰好延伸到\(dep=i\)的位置,的最小费用。

转移方程非常显然:每次把\(dp_x\)和\(dp_v\)合并时\(dp_{x,i}+=\min\{dp_v\},dp_{v,i}+=\min\{dp_x\}\),然后对应位置取\(\min\)即可。

显然这东西可以用线段树合并维护,就做完了。

然而这题卡空间,需要垃圾回收。

线段树合并记得启发式合并!

我一定是太久没写线段树合并了……

不过最后几组数据(多半是hack数据)把我hack掉了,我在输出时特判才过。也许是炸long long的锅,但空间不允许我开__int128。


代码

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pil pair<int,ll>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 303030
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(register int x)
{
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; int n,m;
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
edge[++ecnt]=(hh){t,head[f]};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t]};
head[t]=ecnt;
} #define Tree (sz*20)
ll tr[Tree],tag[Tree];
int ls[Tree],rs[Tree],size[Tree],cnt;
int bin[Tree],top;
void del(int k){tr[k]=1e17;tag[k]=ls[k]=rs[k]=0;if (top<Tree-1) bin[++top]=k;}
int newnode(){int k=(top?bin[top--]:++cnt);tr[k]=1e17;return k;}
#define lson ls[k],l,mid
#define rson rs[k],mid+1,r
void Add(int k,ll w){if (!k) return;tr[k]+=w;tag[k]+=w;}
void pushdown(int k){Add(ls[k],tag[k]);Add(rs[k],tag[k]);tag[k]=0;}
void ins(int &k,int l,int r,int x,ll y)
{
if (!k) size[k=newnode()]=1;
chkmin(tr[k],y);
if (l==r) return;
pushdown(k);
int mid=(l+r)>>1;
if (x<=mid) ins(lson,x,y);
else ins(rson,x,y);
size[k]=size[ls[k]]+size[rs[k]];
}
ll query(int k,int l,int r,int x,int y)
{
if (!k) return 1e17;
if (x<=l&&r<=y) return tr[k];
int mid=(l+r)>>1;ll ret=1e17;
pushdown(k);
if (x<=mid) chkmin(ret,query(lson,x,y));
if (y>mid) chkmin(ret,query(rson,x,y));
return ret;
}
int root[sz];
void merge(int &k,int l,int r,int &k2)
{
if (!k2) return;
if (!k) size[k=newnode()]=1;
if (size[k]<size[k2]) swap(k,k2);
chkmin(tr[k],tr[k2]);
if (l==r) return del(k2);
int mid=(l+r)>>1;
pushdown(k);pushdown(k2);
merge(lson,ls[k2]);
merge(rson,rs[k2]);
del(k2);
size[k]=size[ls[k]]+size[rs[k]];
} vector<pil>V[sz];
int dep[sz]; void dfs(int x,int fa)
{
dep[x]=dep[fa]+1;
ins(root[x],1,n,dep[x],0);
#define v edge[i].t
go(x) if (v!=fa)
{
dfs(v,x);
ll w1=query(root[x],1,n,1,dep[x]),w2=query(root[v],1,n,1,dep[x]);
Add(root[x],w2);Add(root[v],w1);
merge(root[x],1,n,root[v]);
}
#undef v
ll w;
for (auto v:V[x])
w=query(root[x],1,n,1,dep[x]),ins(root[x],1,n,dep[v.fir],w+v.sec);
} int main()
{
file();
int x,y,z;
read(n,m);
rep(i,1,n-1) read(x,y),make_edge(x,y);
rep(i,1,m) read(x,y,z),V[x].push_back(MP(y,z));
dfs(1,0);
ll ans=query(root[1],1,n,1,1);
printf("%lld",ans>=1e16||ans<0?-1ll:ans);
return 0;
}

Codeforces 671D Roads in Yusland [树形DP,线段树合并]的更多相关文章

  1. 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)

    点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...

  2. 【pkuwc2018】 【loj2537】 Minmax DP+线段树合并

    今年年初的时候参加了PKUWC,结果当时这一题想了快$2h$都没有想出来.... 哇我太菜啦.... 昨天突然去搜了下哪里有题,发现$loj$上有于是就去做了下. 结果第一题我5分钟就把所有细节都想好 ...

  3. [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)

    还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...

  4. Codeforces 666E Forensic Examination SAM or SA+线段树合并

    E. Forensic Examination http://codeforces.com/problemset/problem/666/E 题目大意:给模式串S以及m个特殊串,q个询问,询问S的子串 ...

  5. BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)

    BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...

  6. LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】

    LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...

  7. [PKUWC2018]Minimax [dp,线段树合并]

    好妙的一个题- 我们设 \(f_{i,j}\) 为 \(i\) 节点出现 \(j\) 的概率 设 \(l = ch[i][0] , r = ch[i][1]\) 即左儿子右儿子 设 \(m\) 为叶子 ...

  8. P6847-[CEOI2019]Magic Tree【dp,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/P6847 题目大意 \(n\)个点的一棵树上,每个时刻可以割掉一些边,一些节点上有果实表示如果在\(d_i\)时刻这 ...

  9. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

随机推荐

  1. 【Linux】排序命令sort

    很多时候,我们都会去计算一次数据里头的相同型态的数据总数,举例来说, 使用 last 可以查得这个月份有登陆主机者的身份.那么我可以针对每个使用者查出他们的总登陆次数吗? 此时就得要排序与计算之类的命 ...

  2. webservlce 的各个属性

    [WebMethod(Description = "我是可见的", MessageName = "GetAboutIntroduction")]//有这个标志的 ...

  3. Linux下运行jmeter

    • 我们在做测试的时候,有时候要运行很久,公司用的测试服务器一般都是linux,就可以运行在linux下面,linux下面不能像windows一样有图形化界面,那怎么运行脚本呢,就先在windows上 ...

  4. LOJ #6268 分拆数

    不会五边形数的菜鸡的分块乱搞 LOJ #6268 题意 求前$ n$个数的整数划分方案数,$ n \leq 10^5$ $ Solution$ 考虑暴力$ DP$ $ f(x,y)$表示放了$ x$个 ...

  5. window 编译lua 5.3

    由于lua 5.1 不支持左移右移的操作符,所以要移植lua 5.3.方便在window 下编译调试 参考链接: http://www.linuxidc.com/Linux/2014-02/96459 ...

  6. mkyaffs2image 生成不了120M的镜像文件的解决方法

    下载链接:   http://download.csdn.net/download/macrocrazier/3807761 用上述下载的链接会出现Failed to execute /linuxrc ...

  7. Django REST Framework API Guide 02

    本节大纲 1.Generic Views 2.ViewSets  1.Generic Views CBV的主要的一个优点就是极大的允许了对于代码的从用.自然,rest framework取其优势,提供 ...

  8. NIO & Netty框架学习

    channle buffer selector.selectionKey 关于websocket http://lixiaohui.iteye.com/blog/2328068 长连接和短连接 htt ...

  9. html转成pdf,下载(html2canvas 和 jsPDF)

    参考链接:https://github.com/linwalker/render-html-to-pdf

  10. springboot整合JSP以及发布项目到独立的tomcat中与打成jar包使用

    之前研究了springboot整合freemarker与thymeleaf的使用.也研究了springboot发布到独立的tomcat的使用以及使用自带的tomcat打成jar包的使用,下面研究集成J ...