正题

题目链接:https://uoj.ac/problem/284


题目大意

nnn个点的一棵树,每个点有一个wiw_iwi​表示至少死亡wiw_iwi​次才能通过这个点,否则就会死亡。只能往子节点走,mmm此询问从sis_isi​走到tit_iti​至少要死多少次。


解题思路

也就算我们要尽早让死亡次数到达s−>ts->ts−>t路径上的最大值mxmxmx。

考虑比较朴素的做法,设fx,if_{x,i}fx,i​表示节点xxx的子树中与它距离不超过iii的节点中wiw_iwi​的最大值。那么我们处理完这个数组后对于每个询问可以二分到一个ddd使得fx,d≥wif_{x,d}\geq w_ifx,d​≥wi​然后答案就是mx∗d−∑i=1d−1fx,imx*d-\sum_{i=1}^{d-1}f_{x,i}mx∗d−∑i=1d−1​fx,i​
具体原理就是先默认每次死亡都要到ddd那么远,然后中间的一些值可以减去。

那么考虑如何快速计算fff,因为它与深度有关,所以考虑长链剖分。fx,if_{x,i}fx,i​是可以继承fy,i+1f_{y,i+1}fy,i+1​的,但是插入时我们发现这是一个让后缀取maxmaxmax的操作,因为fx,if_{x,i}fx,i​是随着iii单调递增的,所以我们可以使用线段树。用线段树上二分+区间修改和求和就可以快速计算fff和计算答案。

世界复杂度O(nlog⁡n)O(n\log n)O(nlogn)


codecodecode

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
#define dis(x) (dep[x]-dep[top[x]])
using namespace std;
const ll N=3e5+10,T=18,M=N<<4;
struct node{ll to,next;
}a[N<<1];
ll n,m,tot,c[N],ls[N],len[N],dep[N],top[N];
ll cnt,son[N],d[N],ans[N],f[N][T+1],g[N][T+1];
vector<int> q[N];
struct Seq_Tree{ll n;vector<ll> w,v,lazy;void init(ll L){w.resize(L<<2,0);v.resize(L<<2,0);lazy.resize(L<<2,0);n=L-1;return;}void Downdata(ll x,ll l,ll r){if(!lazy[x])return;ll mid=(l+r)>>1;lazy[x*2]=lazy[x*2+1]=lazy[x];v[x*2]=v[x*2+1]=lazy[x];w[x*2]=(mid-l+1)*lazy[x];w[x*2+1]=(r-mid)*lazy[x];lazy[x]=0;return;}void Change(ll x,ll L,ll R,ll l,ll r,ll val){if(L==l&&R==r){lazy[x]=v[x]=val;w[x]=(R-L+1)*val;return;}ll mid=(L+R)>>1;Downdata(x,L,R);if(r<=mid)Change(x*2,L,mid,l,r,val);else if(l>mid)Change(x*2+1,mid+1,R,l,r,val);else Change(x*2,L,mid,l,mid,val),Change(x*2+1,mid+1,R,mid+1,r,val);w[x]=w[x*2]+w[x*2+1];v[x]=max(v[x*2],v[x*2+1]);return;}ll Find(ll x,ll l,ll r,ll k){if(v[x]<k)return n+1; if(l==r)return l;ll mid=(l+r)>>1;Downdata(x,l,r);if(v[x*2]>=k)return Find(x*2,l,mid,k);return Find(x*2+1,mid+1,r,k);}void Insert(ll x,ll w){ll y=Find(1,0,n,w);if(y>x)Change(1,0,n,x,y-1,w);return;}ll Ask(ll x,ll L,ll R,ll l,ll r){if(L==l&&R==r)return w[x];ll mid=(L+R)>>1;Downdata(x,L,R);if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return Ask(x*2,L,mid,l,mid)+Ask(x*2+1,mid+1,R,mid+1,r);}ll Query(ll l,ll r){return Ask(1,0,n,l,r);}
}t[N];
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void init(){for(ll j=1;j<=T;j++)for(ll i=1;i<=n;i++){f[i][j]=f[f[i][j-1]][j-1];g[i][j]=max(g[i][j-1],g[f[i][j-1]][j-1]);}
}
ll get_max(ll s,ll t){ll w=0;for(ll i=T;i>=0;i--)if(dep[f[t][i]]>dep[s])w=max(w,g[t][i]),t=f[t][i];return w;
}
void dfs(ll x){len[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;dfs(y);len[x]=max(len[x],len[y]+1);if(len[y]>len[son[x]])son[x]=y;}return;
}
void solve(ll x){if(top[x]==x)t[x].init(len[x]);if(son[x]){top[son[x]]=top[x];solve(son[x]);}for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==son[x])continue;top[y]=y;solve(y);for(ll j=0;j<len[y];j++)t[top[x]].Insert(dis(x)+j+1,t[y].Query(j,j));}for(ll i=0;i<q[x].size();i++){ll p=q[x][i],k=top[x];ll pos=t[k].Find(1,0,len[k]-1,d[p]);if(pos>dis(x))ans[p]-=t[k].Query(dis(x),pos-1);ans[p]+=d[p]*(pos-dis(x));}t[top[x]].Insert(dis(x),c[x]);return;
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&c[i]);dep[1]=1;for(ll i=2;i<=n;i++){scanf("%lld",&f[i][0]);dep[i]=dep[f[i][0]]+1;g[i][0]=c[f[i][0]];addl(f[i][0],i);}init();scanf("%lld",&m);for(ll i=1;i<=m;i++){ll s,t;scanf("%lld%lld",&s,&t);ans[i]=dep[t]-dep[s];d[i]=get_max(s,t);q[s].push_back(i);}dfs(1);top[1]=1;solve(1);for(ll i=1;i<=m;i++)printf("%lld\n",ans[i]);return 0;
}

UOJ#284-快乐游戏鸡【长链剖分,线段树】相关推荐

  1. P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】

    正题 题目链接:https://www.luogu.com.cn/problem/P4292 题目大意 给出nnn个点的一棵树,然后求长度在[L,U][L,U][L,U]之间的一条路径的平均权值最大. ...

  2. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  4. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  5. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  6. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  7. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

  8. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  9. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

最新文章

  1. Open Source的一些网站,自己收集来的
  2. python爬虫从入门到精通-Python网络爬虫开发从入门到精通
  3. linux复盘:构架搭建lamp(安装)
  4. Winform中设置ZedGraph的曲线为折线、点折线、散点图
  5. NIO和BIO如何影响应用程序的设计-数据处理
  6. php 获取设备,PHP获取设备类型实例代码
  7. asl不成功怎么算_那些减肥成功还不反弹的人是怎么做到的?
  8. Linux环境下的Popush部署——张凯
  9. property修饰关键字
  10. [多线程] Thread
  11. javascript设计模式_JavaScript 设计模式 学习总结
  12. PyTorch 1.0 中文官方教程:用例子学习 PyTorch
  13. thinkpad 使用技巧
  14. html表单input file,最简单的方法美化表单中input type=file元素
  15. extjs 教程 java_ExtJS6.2学习
  16. html的视频字幕制作步骤,十大字幕制作软件
  17. 一生之书《悉达多》接受这个世界,爱它,属于它
  18. 开机提示grub可咋办啊
  19. 苹果邮箱怎么登录qq邮箱_怎么登陆邮箱?公司mail邮箱在哪登录?
  20. 第一个C语言项目——图书管理系统

热门文章

  1. win2003无法进入桌面_救急,如何通过命令行备份桌面重要文件?
  2. 织梦首页html在哪儿,dedecms织梦首页去index.html
  3. linux查看mq是否启动的命令,rocketmq查看命令
  4. mysql判断表存在的sql语句_SQL 语句判断已知表是否存在_MySQL
  5. java 接口的静态方法_Java8新特性:接口的默认方法与接口的静态方法
  6. python中x 1什么意思_Python:A [1:]中x的含义是什么?
  7. vue 离开页面事件_【必看】58 道 Vue 常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度...
  8. leetcode209. 长度最小的子数组(暴力+滑动窗口)
  9. map容器实现一对多
  10. 地理生物高考成绩查询2021,2021北京中考地理生物成绩查询时间【已公布】