首页 > 其他分享 >P2305 [NOI2014] 购票

P2305 [NOI2014] 购票

时间:2022-10-06 15:35:18浏览次数:51  
标签:pre ch int text 购票 tp pos NOI2014 P2305

P2305 [NOI2014] 购票

设 \(f_{x}\) 表示从 \(x\) 点跳到 \(1\) 的最少费用。考虑 \(x\) 的一个祖先 \(u\),有

\[f_x=f_{u}+\text{dis}_{u,x}\times p_x+q_x \]

其中需要满足 \(\text{dis}_{u,x}\le l_x\)。

由于 \(p\) 为 \(x\) 的祖先,考虑前缀和来化简 \(\text{dis}_{u,x}\)。记 \(\text{pre}_x\) 表示根节点 \(1\) 到 \(x\) 的简单路径长度。则有 \(\text{dis}_{u,x}=\text{pre}_x-\text{pre}_p\)。带入原式并化简得到

\[f_{x}=f_u+\text{pre}_x\times p_x-\text{pre}_u\times p_x+q_x \]

将 \(-\text{pre}_u\) 看作 \(k\),容易得到斜率优化的形式。

由于需要满足条件 \(\text{pre}_x-\text{pre}_p \le l_x\),考虑外层套用线段树,则内层使用李超线段树实现较为简单。

由于需要找到点的祖先节点区间,线段树遍历顺序采用原树的出栈序。

至此,可以得到一个线段树套李超线段树的 \(\mathcal{O}(n \log^2 n)\) 的做法,可以通过。

#include<bits/stdc++.h>
using namespace std;
namespace IO{
	template<typename T>inline bool read(T &x){
		x=0;
		char ch=getchar();
		bool flag=0,ret=0;
		while(ch<'0'||ch>'9') flag=flag||(ch=='-'),ch=getchar();
		while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(),ret=1;
		x=flag?-x:x;
        return ret;
	}
	template<typename T,typename ...Args>inline bool read(T& a,Args& ...args){
	    return read(a)&&read(args...);
	}
	template<typename T>void prt(T x){
		if(x>9) prt(x/10);
		putchar(x%10+'0');
	}
	template<typename T>inline void put(T x){
		if(x<0) putchar('-'),x=-x;
		prt(x);
	}
	template<typename T>inline void put(char ch,T x){
		if(x<0) putchar('-'),x=-x;
		prt(x);
		putchar(ch);
	}
	template<typename T,typename ...Args>inline void put(T a,Args ...args){
	    put(a);
		put(args...);
	}
	template<typename T,typename ...Args>inline void put(const char ch,T a,Args ...args){
	    put(ch,a);
		put(ch,args...);
	}
	inline void put(string s){
		for(int i=0,sz=s.length();i<sz;i++) putchar(s[i]);
	}
	inline void put(const char* s){
		for(int i=0,sz=strlen(s);i<sz;i++) putchar(s[i]);
	}
}
using namespace IO;
#define N 200005
#define M 1000005 
#define Maxn 1000000
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
int n,typ,cnt,head[N],num; 
struct object{
	ll f,s,p,q,l;
}a[N];
struct edge{
	int v,nxt;
}e[N<<1];
inline void add(int u,int v){
	e[++cnt]=(edge){v,head[u]},head[u]=cnt;
}
struct line{
	ll k,b;
}L[N];
inline int insert(ll k,ll b){
	L[++num]=(line){k,b};
	return num;
}
inline ll calc(int id,ll x){
	return L[id].k*x+L[id].b;
}
struct LC_Tree{
	struct node{
		int ls,rs,s;
	}t[M*30];
	#define lc(x) t[x].ls
	#define rc(x) t[x].rs
	#define s(x) t[x].s
	int Idx;
	inline void update(int &x,int l,int r,int pos){
		if(!x) return t[x=++Idx].s=pos,void();
		int mid=l+r>>1;
		if(calc(s(x),mid)>calc(pos,mid)) swap(s(x),pos);
		if(calc(s(x),l)>calc(pos,l)) update(lc(x),l,mid,pos);
		if(calc(s(x),r)>calc(pos,r)) update(rc(x),mid+1,r,pos);
	}
	inline ll query(int x,int l,int r,int pos){
		if(!x) return inf;
		ll res=calc(s(x),pos);
		int mid=l+r>>1;
		if(pos<=mid) res=min(res,query(lc(x),l,mid,pos));
		else res=min(res,query(rc(x),mid+1,r,pos));
		return res;
	}
	#undef lc
	#undef rc
	#undef s
}T;
int rt[N<<2];
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
inline void update(int x,int l,int r,int pos,int k){
	T.update(rt[x],0,Maxn,k);
	if(l==r) return;
	int mid=l+r>>1;
	if(pos<=mid) update(lc(x),l,mid,pos,k);
	else update(rc(x),mid+1,r,pos,k);
}
inline ll query(int x,int l,int r,int ql,int qr,int k){
	if(ql<=l&&qr>=r) return T.query(rt[x],0,Maxn,k);
	ll res=inf;
	int mid=l+r>>1;
	if(ql<=mid) res=min(res,query(lc(x),l,mid,ql,qr,k));
	if(qr>mid) res=min(res,query(rc(x),mid+1,r,ql,qr,k));
	return res;
}
#undef lc
#undef rc
ll f[N],pre[N];
int id[N],idx,tp,c[N];
inline void prework(int x){
	for(int i=head[x];i;i=e[i].nxt) prework(e[i].v);
	id[x]=++idx;
}
inline void dfs(int x){
	update(1,1,n,id[x],insert(-pre[tp],f[x]));
	c[tp]=x;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].v;
		tp++;
		pre[tp]=pre[tp-1]+a[v].s;
		int L=id[v],R=id[c[lower_bound(pre,pre+tp,pre[tp]-a[v].l)-pre]];
		f[v]=query(1,1,n,L,R,a[v].p)+pre[tp]*a[v].p+a[v].q;
		dfs(v),c[tp]=0,tp--;
	}
}
int main(){
	read(n,typ);
	for(int i=2;i<=n;i++)
		read(a[i].f,a[i].s,a[i].p,a[i].q,a[i].l),add(a[i].f,i);
	prework(1),dfs(1);
	for(int i=2;i<=n;i++) put('\n',f[i]);
	return 0;
}

标签:pre,ch,int,text,购票,tp,pos,NOI2014,P2305
From: https://www.cnblogs.com/fzj2007/p/16757706.html

相关文章

  • P3238 [HNOI2014]道路堵塞
    P3238HNOI2014道路堵塞点击查看代码#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<utility>#include<array>#incl......
  • P2375 [NOI2014] 动物园
    定义字符串的前\(i\)个字符组成的字符串中一最大子串\(T\)即使前缀也是后缀,且\(|T|\leqi/2\),则定义\(num[i]=|T|\),求\(num[i]+1\)之积\(mod\)1000000007。\(......