ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2014] 购票

2021-05-23 08:33:17  阅读:253  来源: 互联网

标签:int res 购票 dfs NOI2014 maxn 重链 define


这题怎么都做过了/kk

感谢 Fz 的题解!

首先这题有一个 DP 式子,

\[f_i = d_i \times p_i + q_i +\min(-d_j\times p_i+f_j) \]

明显是斜率优化的形式。

但对于 \(u\) 有贡献的只有离他较近的若干个祖先。

这里就有几个做法;

  1. 点分
  2. 树剖,u 到某个祖先可以剖为 若干条重链的前缀 + 一条重链的中间一段,然后丢在重链上处理。
  3. 在 dfs 的过程中,维护一个可撤销的单调栈(用来维护凸包)
  4. 一种巧妙的做法:首先 dfs ,在每个点 dfs 出去的时候记上时间戳,可以得到出栈序。dfs DP 的时候,维护一个线段树套李超树(或者单调栈维护凸包也行),每次到 u 时,查询的就是 [ u 的出栈序 到 那个祖先的出栈序 ] 这一段区间的点,进行转移。

这种方法也许在处理其他题(从上到下的查询?)时也有用。

贺来的代码

#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define int long long 
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}

#define fi first
#define se second
#define pb push_back
#define mkp make_pair
typedef pair<int,int>pii;
typedef vector<int>vi;

#define maxn 200005
#define N   4000005
int n;
vector<int>e[maxn];

int k[maxn],b[maxn],cnt,rt[maxn<<2];
inline int f(int id,int x){return k[id]*x+b[id];}
int tag[N],ls[N],rs[N];
void upd(int&p,int l,int r,int x)
{
	if(!p)p=++cnt;
	if(!tag[p])return tag[p]=x,void();
	int mid=l+r>>1;
	if(f(x,mid)<f(tag[p],mid))swap(x,tag[p]);
	if(l<r) k[x]<k[tag[p]]?upd(rs[p],mid+1,r,x):upd(ls[p],l,mid,x);
}
int qry(int p,int l,int r,int x)
{
	if(!p)return 1e18;
	int mid=l+r>>1;
	return min(f(tag[p],x),x<=mid?qry(ls[p],l,mid,x):qry(rs[p],mid+1,r,x));
}

void modify(int p,int l,int r,int x,int v)
{
	upd(rt[p],0,1e6,v);
	if(l==r)return;
	int mid=l+r>>1;
	x<=mid?modify(p<<1,l,mid,x,v):modify(p<<1|1,mid+1,r,x,v);
}
int ask(int p,int l,int r,int ql,int qr,int v)
{
	if(l>=ql&&r<=qr)return qry(rt[p],0,1e6,v);
	int mid=l+r>>1,res=1e18;
	if(ql<=mid)res=min(res,ask(p<<1,l,mid,ql,qr,v));
	if(qr>mid)res=min(res,ask(p<<1|1,mid+1,r,ql,qr,v));
	return res; 
}

int o[maxn],idx;
void getO(int u){
	for(auto v:e[u])getO(v);
	o[u]=++idx;
}
int s[maxn],p[maxn],q[maxn],l[maxn],fa[maxn];
int dp[maxn],dis[maxn],top,id[maxn];
void dfs(int u)
{
	k[u]=-dis[top],b[u]=dp[u];
	id[top]=u;
	modify(1,1,n,o[u],u);
	for(auto v:e[u]){
		++top,dis[top]=dis[top-1]+s[v];
		int anc=id[lower_bound(dis,dis+top,dis[top]-l[v])-dis];
		dp[v]=ask(1,1,n,o[v],o[anc],p[v]);
		dp[v]=dp[v]+dis[top]*p[v]+q[v];
		dfs(v);
		--top;
	}
}

signed main()
{
	n=read(),read();
	For(i,2,n){
		fa[i]=read(),s[i]=read(),p[i]=read(),q[i]=read(),l[i]=read();
		e[fa[i]].pb(i);
	}
	getO(1);
	dfs(1);
	For(i,2,n)printf("%lld\n",dp[i]);
	return 0;
}

标签:int,res,购票,dfs,NOI2014,maxn,重链,define
来源: https://www.cnblogs.com/Rainbowsjy/p/14800410.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有