51 nod 1789 跑的比谁都快

1789 跑的比谁都快 
基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160  难度:6级算法题

香港记者跑的比谁都快是众所周知的常识。

现在,香港记者站在一颗有  n 个点的树的根结点上(即1号点),编号为  i 的点拥有权值  a[i] ,数据保证每个点的编号都小于它任意孩子结点的别号。

我们假定这棵树的每个叶子结点都在发生一个大新闻,香港记者要用最少的耗时去报道其中的任意一个。

若香港记者目前处于第  i 号点上,那么它可以移动至以  i 为根的子树上的任意一点  j ,耗时  a[i]+(ji)p ,p为给定常数。

请问这位香港记者搞哪个大新闻的耗时最短?所耗时间是多少?
Input
第一行两个数n<=100000、p<=10,代表树上点的个数以及题中所提及的常数p。
接下来n行,第i行有两个数字a[i]<10^6、fa[i] 
    
Output
每组数据输出一行为最短耗时。
Input示例
10 2
833 0
2076 1
5759 1
5671 3
6642 2
3712 4
8737 1
5139 6
8800 1
6638 1
Output示例
849
题解:

这道题蕴含一种思想:从特殊到一般 , 直接考虑树形结构会发现无从下手 , 但从链 ---> 树进行转换 , 就可以发现正解
对于一条链:f[i] = max(f[i] , f[j] + a[j] + (i - j)^p) , 显然算法是n^2的 , 转化成树 ,就是将根节点到每个叶子节点的路径单独考虑,最后统计每个叶子节点的
最小值。
可是如何优化时间复杂度呢?
由于转移方程中有一部分是指数形式的,呈暴增趋势 , 但存在一种情况,就是(i - j ^ p)较小, 但a[j]较大所以必然存在一个临界值 , 这也依赖于一个性质:
对于节点i , j  , x, deep[i] < deep[j] < deep[x] , 若f[i] + cost(i --> x) >= f[j] + cost(j --> x) , 显然在j包含的所有叶子节点不可能从i转移过来,而且要注意为什么是
等号:如果两种花费相同 , 显然深度越大的使得(a - b)^ p部分 更小 , 所以淘汰i。
上述操作可以用队列来完成 , 即不断去掉队首的元素,那么可不可以也去掉队尾的一些元素呢
还是上述性质 , 对于队列中末尾两个节点 , 可以找上面说的那个临界值 ,同时这找出队尾节点和当前节点的临界值 ,  判断一下 , 所谓临界值V(i , j)(i和j的临界值 , deep[i] < deep[j])的含义就是 :编号大于等于 临界值的 
节点从j转移过来最有 , 编号 小于临界值的节点从i好转移过来最优 , 寻找方法当然是二分答案了(EFDA), 若V(que[tail - 1] , que[tail]) > V(que[tail] , x) , 说明que[tail]的节点无论如何都不会最优(画图理解),这样就可以不断删除队尾元素了。
这些操作的思想就是发现单调性 , 运用斜率优化类似操作进行优化 。
总的来说是一道不错的有思想的题目。 

/*
51 nod 1789
这道题蕴含一种思想:从特殊到一般 , 直接考虑树形结构会发现无从下手 , 但从链 ---> 树进行转换 , 就可以发现正解
对于一条链:f[i] = max(f[i] , f[j] + a[j] + (i - j)^p) , 显然算法是n^2的 , 转化成树 ,就是将根节点到每个叶子节点的路径单独考虑,最后统计每个叶子节点的
最小值。
可是如何优化时间复杂度呢?
由于转移方程中有一部分是指数形式的,呈暴增趋势 , 但存在一种情况,就是(i - j ^ p)较小, 但a[j]较大所以必然存在一个临界值 , 这也依赖于一个性质:
对于节点i , j  , x, deep[i] < deep[j] < deep[x] , 若f[i] + cost(i --> x) >= f[j] + cost(j --> x) , 显然在j包含的所有叶子节点不可能从i转移过来,而且要注意为什么是
等号:如果两种花费相同 , 显然深度越大的使得(a - b)^ p部分 更小 , 所以淘汰i。
上述操作可以用队列来完成 , 即不断去掉队首的元素,那么可不可以也去掉队尾的一些元素呢
还是上述性质 , 对于队列中末尾两个节点 , 可以找上面说的那个临界值 ,同时这找出队尾节点和当前节点的临界值 ,  判断一下 , 所谓临界值V(i , j)(i和j的临界值 , deep[i] < deep[j])的含义就是 :编号大于等于 临界值的 
节点从j转移过来最有 , 编号 小于临界值的节点从i好转移过来最优 , 寻找方法当然是二分答案了(EFDA), 若V(que[tail - 1] , que[tail]) > V(que[tail] , x) , 说明que[tail]的节点无论如何都不会最优(画图理解),这样就可以不断删除队尾元素了。
这些操作的思想就是发现单调性 , 运用斜率优化类似操作进行优化 。
总的来说是一道不错的有思想的题目。 
*/
#include 
using namespace std;
#define ll long long
#define N 2000000
#define Max 1e18
#define Rate(i , k) (f[i] + M[k - i] + a[i])
ll L , R , last[N] , head[N] , to[N] , cnt = 0 , top = 0 , a[N] , M[N] , ans , n , f[N] , mx; 
inline ll read()
{
	ll x = 0 , f = 1ll; char ch = getchar();
	while(ch < '0' || ch > '9') { if(ch == '-') f = -1ll; ch = getchar();}
	while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar();}
	return x * f;
}

inline void ins(ll u ,ll v)
{
	last[++cnt] = head[u] , head[u] = cnt , to[cnt] = v;
}

struct node
{
	ll pre , x , sub;
}sta[N];

inline ll EFDA(ll x , ll y)
{
	ll l = x + 1 , r = n , res = x + 1 , mid;
	while(l <= r)
	{
		mid = (l + r) / 2;
		if(f[x] + M[mid - x] + a[x] < f[y] + M[mid - y] + a[y])  l = mid + 1 , res = mid;
		else r = mid - 1;
	}
	return res;
}

inline void dfs(ll x)
{
	ll l = L , r = R , i , lst , Nowr;
	
	for( ;sta[L].sub && Rate(sta[L].x , x) >= Rate(sta[sta[L].sub].x , x) ;  L = sta[L].sub);
	
	f[x] = (x - sta[L].x < mx) ? Rate(sta[L].x , x) : Max;
	
	if(!head[x] && ans > f[x]) ans = f[x];
	
	for( ; sta[R].pre && EFDA(sta[sta[R].pre].x , sta[R].x) >= EFDA(sta[R].x , x) ; R = sta[R].pre);
	
	lst = sta[R].sub , Nowr = R;
	sta[++top].pre = R , sta[top].x = x , sta[top].sub = 0 , sta[R].sub = top , R = top;
	
	for(i = head[x] ; i ; i = last[i]) dfs(to[i]);
	
	sta[Nowr].sub = lst , L = l , R = r;
}

int main()
{ 
//	freopen("test.in" , "r" , stdin);
	ll i , j , k , x , p;
	n = read() , p = read();
	for(i = 1 ; i <= n ; ++i) a[i] = read() , x = read() , ins(x , i);
	for(i = 1 ; i <= n ; ++i)
	{
		M[i] = 1ll;
		for(j = 1 ; j <= p ; ++j)
		{
			if((M[i] *= i) > Max) break;
		}
		if(M[i] > Max) break;
	}
	mx = (M[i] > Max ? i - 1 : i);
	ans = Max;
	sta[++top].pre = 0 , sta[top].x = 1 , sta[top].sub = 0 , L = R = 1;
	for(i = head[1] ; i ; i = last[i]) dfs(to[i]);
	printf("%lld\n" , ans);
	return 0;
}


你可能感兴趣的:(dp——斜率优化,树形dp,动态规划好题)