首页 > 其他分享 >树上分块解决限制距离的树上 DP 问题([NOI2014] 购票)

树上分块解决限制距离的树上 DP 问题([NOI2014] 购票)

时间:2023-01-12 20:23:15浏览次数:62  
标签:ch val 分块 int ll NOI2014 read 树上 DP

[NOI2014] 购票

大家好,我喜欢暴力数据结构,所以我用分块过了此题。


转移方程很简单:

\[f_u=\min_{d_u-d_v\leq l_u}{(d_u-d_v)\times p_u+q_u+f_v} \]

\[f_u=d_u\times p_u+q_u\min_{d_v\geq l_u-d_u}{-d_v\times p_u+f_v} \]

后面那部分一条 \(y=kx+b\) 的直线在 \(x=p_u\) 处的取值,很容易想到用李超线段树维护了。

如果没有距离限制的话,就可以直接用可持久化李超线段树解决。(或者可撤销李超树?)

加上距离的限制的话,想到 P4192 旅行规划 中分块维护凸包的做法,于是对于 \(t=0\) 或 \(2\) 的数据点就解决了。

转化到树上,也可以分块解决。

对深度进行分块。设块长为 \(B\) 深度 \(\left[kB,(k+1)B\right)\) 的分为一层,每一层内部进行可持久化上下继承信息。不同层之间互不影响。

实际上是借助可持久化数据结构不受兄弟影响的性质把树夹扁成一条链了。

询问使如果该节点到这一层顶端都在距离限制以内,就直接在李超树上查询,然后跳到上面一层。

容易维护出 \(pre_i\) 表示 \(i\) 号节点的祖先(包括自己)中最下面一个深度为 \(B\) 的整数倍的节点。

然后散块暴力转移就好。

块长 \(B\) 取 \(\sqrt{n\log n}\) 时,复杂度为 \(n\sqrt{n\log n}\)。

实际上跑得挺快的,特判了 \(t=0\) 或 1 的数据点后在最优解第二页,而且代码很短!五十行,1.74K 是最优解前四页里面最短的了。

#include<bits/stdc++.h>
#define EL puts("Elaina")
#define reg register int
typedef long long ll;
using namespace std;
namespace IO{
	const int siz=1<<18;char buf[siz],*p1,*p2;
	inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,siz,stdin),p1==p2)?EOF:*p1++;}
	template<typename T> inline T read(){
		T x=0;char ch=getc();
		while(!isdigit(ch))ch=getc();
		while(isdigit(ch))x=x*10+(ch^48),ch=getc();
		return x;
	}
}using IO::read;
const int maxn=2e5+3;const ll INF=0x3f3f3f3f3f3f3f3f;
struct line{ll k,b;inline ll operator ()(const int &x)const{return k*x+b;}};
int tot;
#define mid (l+r>>1)
struct SegmentTree{
	struct{int lt,rt;line val;}t[maxn*26];
	inline void insert(int &p,int q,int l,int r,line val){
		t[p=++tot]=t[q];
		if(val(mid)<t[p].val(mid))swap(val,t[p].val);
		if(l==r)return;
		if(val.k>t[p].val.k)insert(t[p].lt,t[q].lt,l,mid,val);
		else insert(t[p].rt,t[q].rt,mid+1,r,val);
	}
	inline void query(int k,int l,int r,int x,ll &ans){
		ans=min(ans,t[k].val(x));if(!k||l==r)return;
		x<=mid?query(t[k].lt,l,mid,x,ans):query(t[k].rt,mid+1,r,x,ans);
	}
}T;
#undef mid
int n,block,fa[maxn],pre[maxn],dep[maxn],root[maxn];ll d[maxn],f[maxn];
inline void MyDearMoments(){
	n=read<int>(),T.t[0].val.b=INF,block=read<int>()<2?n+1:sqrt(n*log(n));
	T.insert(root[1],0,0,1000000,{0,0});
	for(reg i=2;i<=n;++i){
		int u=fa[i]=read<int>();d[i]=read<ll>()+d[fa[i]];
		int p=read<int>();ll q=read<ll>(),lim=d[i]-read<ll>();
		dep[i]=dep[u]+1,pre[i]=dep[i]%block==0?i:pre[u],f[i]=LLONG_MAX;
		while(u&&d[pre[u]]>=lim)T.query(root[u],0,1000000,p,f[i]),u=fa[pre[u]];
		while(u&&d[u]>=lim)f[i]=min(f[i],-d[u]*p+f[u]),u=fa[u];
		printf("%lld\n",f[i]+=d[i]*p+q);
		T.insert(root[i],dep[i]%block==0?0:root[fa[i]],0,1000000,{-d[i],f[i]});
	}
}
int main(){return MyDearMoments(),0;}

标签:ch,val,分块,int,ll,NOI2014,read,树上,DP
From: https://www.cnblogs.com/muel-imj/p/17047833.html

相关文章

  • python udp 接收图片并保存在本地
     疑问1.发送图片是以什么格式2.字节数据怎么保存到本地3.怎么对传输不同设备发送的图片进行分类存储4.udp实现解答1.以字节a.先用cv......
  • P6374 「StOI-1」树上询问
    P6374「StOI-1」树上询问Description给定一颗\(n\)个节点的树,有\(q\)次询问。每次询问给一个参数三元组\((a,b,c)\),求有多少个\(i\)满足这棵树在以\(i\)为......
  • Oracle impdp使用content=data_only会阻塞其他会话DML操作
     Oracleimpdp使用content=data_only会阻塞其他会话DML操作 上篇提到了insert/*+append*/into会对表持有LOCKED_MODE=6的TM锁,导致其他对该表的DML都会被阻塞。实......
  • [NOIP2015 提高组] 子串 【计数dp】
    题面https://www.luogu.com.cn/problem/P2679分析CCF数据真的水。不过还是要写下正解:令\(dp[i][j][t][0/1]\)表示\(a\)串前\(i\)个字符,\(b\)串前\(j\)个字符,匹配子串数......
  • 数位 DP
    2023.1.9省选模拟赛IA【题意】给定\(x,y\),求\[\sum\limits_{i\in[0,2^k-x)}\sum\limits_{j\in[y,2^k)}[i\&j=0]\times[(i+x)\&(j-y)=0]\]\(......
  • UDP
    UDPUDP是一种全双工通信协议。UDP协议首部中有一个16位的大长度.也就是说一个UDP能传输的报文长度是64K(包含UDP首部)。如果我们需要传输的数据超过64K,就需要在应用层......
  • JUC源码学习笔记5——1.5w字和你一起刨析线程池ThreadPoolExecutor源码,全网最细doge
    源码基于JDK8文章1.5w字,非常硬核系列文章目录和关于我一丶从多鱼外卖开始话说,王多鱼给好友胖子钱让其投资,希望亏得血本无归。胖子开了一个外卖店卖国宴,主打高端,外卖......
  • 单调队列优化DP
    今天学习了单调队列优化DP,其模型为:\[f_i=\min/\max_{L(i)\lej\leR(i)}\lbracekf_j+val(i,j)\rbrace\]其中\(L,R\)是具有单调性的函数,\(val(i,j)=h_1(i)+h_2(j)\),是分......
  • 关于华普物联HP-ERS-T200串口服务器UDP 连接互联网服务器操作案例
    本案例使用“路由侠”模拟互联网服务器,使用“路由侠”生成的外网地址进行测试。   硬件连接 将HP-ERS-T200通过USB转RS232串口线连接到PC的USB口上,HP......
  • 关于华普物联HP-ERS-T200串口服务器UDP局域网通讯案例
    硬件连接两个HP-ERS-T200分别通过USB转RS232串口线连接到PC的USB口上,通过上位机设置参数,设置完参数后,将两个HP-ERS-T200通过网线直连。 电脑COM口号确认......