UOJ#284-快乐游戏鸡【长链剖分,线段树】
正题
题目链接: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−1fx,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(nlogn)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-快乐游戏鸡【长链剖分,线段树】相关推荐
- P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】
正题 题目链接:https://www.luogu.com.cn/problem/P4292 题目大意 给出nnn个点的一棵树,然后求长度在[L,U][L,U][L,U]之间的一条路径的平均权值最大. ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1153 Solved: 421 [Submit][Sta ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)
题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...
- CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)
题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...
- 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 ...
- BZOJ4127Abs——树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
最新文章
- Open Source的一些网站,自己收集来的
- python爬虫从入门到精通-Python网络爬虫开发从入门到精通
- linux复盘:构架搭建lamp(安装)
- Winform中设置ZedGraph的曲线为折线、点折线、散点图
- NIO和BIO如何影响应用程序的设计-数据处理
- php 获取设备,PHP获取设备类型实例代码
- asl不成功怎么算_那些减肥成功还不反弹的人是怎么做到的?
- Linux环境下的Popush部署——张凯
- property修饰关键字
- [多线程] Thread
- javascript设计模式_JavaScript 设计模式 学习总结
- PyTorch 1.0 中文官方教程:用例子学习 PyTorch
- thinkpad 使用技巧
- html表单input file,最简单的方法美化表单中input type=file元素
- extjs 教程 java_ExtJS6.2学习
- html的视频字幕制作步骤,十大字幕制作软件
- 一生之书《悉达多》接受这个世界,爱它,属于它
- 开机提示grub可咋办啊
- 苹果邮箱怎么登录qq邮箱_怎么登陆邮箱?公司mail邮箱在哪登录?
- 第一个C语言项目——图书管理系统
热门文章
- win2003无法进入桌面_救急,如何通过命令行备份桌面重要文件?
- 织梦首页html在哪儿,dedecms织梦首页去index.html
- linux查看mq是否启动的命令,rocketmq查看命令
- mysql判断表存在的sql语句_SQL 语句判断已知表是否存在_MySQL
- java 接口的静态方法_Java8新特性:接口的默认方法与接口的静态方法
- python中x 1什么意思_Python:A [1:]中x的含义是什么?
- vue 离开页面事件_【必看】58 道 Vue 常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度...
- leetcode209. 长度最小的子数组(暴力+滑动窗口)
- map容器实现一对多
- 地理生物高考成绩查询2021,2021北京中考地理生物成绩查询时间【已公布】