树上路径(path)
树上路径(path)
题目描述
在Berland,有n个城堡。
每个城堡恰好属于一个领主。不同的城堡属于不同的领主。在所有领主中有一个是国王,其他的每个领主都直接隶属于另一位领主,并且间接隶属于国王。一位领主可以拥有任意数量的下属。这些城堡被一些双向的道路连接。两个城堡是连接的当且仅当他们的主人中一位直接隶属于另一位。
每一年,在Berland会发生以下两件事中的一件:
1.野蛮人攻击了城堡c。这是城堡c第一次也会是最后一次被攻击,因为野蛮人从来不攻击同一座城堡超过一次。
2.一个骑士从城堡a出发前往到城堡b。骑士从不重复经过同一座城堡,因此他的路线是唯一确定的。
现在考虑第二类事件。由于从城堡a到b的路途遥远,每个骑士会在他经过的某个城堡停下来休息一次。根据规则,骑士不能停留在第 y 年以后受到过攻击的城堡中。所以,骑士选择了途径的第k个从第 y+1 年开始到现在(当时)没有被攻击过的城堡(不算城堡a和b)。
你,伟大的历史学家,知道Berland历史上的所有m个事件。请你计算,每个骑士是在哪个城堡休息的。如果在从城堡a到城堡b的路上少于k座城堡,那么你可以断定有关这个骑士的记载是有误的。
输入
第一行包含一个整数N,表示城堡数目。
第二行包含N个整数,依次表示编号为 1...N 的城堡领主的上级。特别的,国王没有上级,故用 0 表示。
第三行包含一个整数M,表示事件数目。
接下来M行,每行描述一个事件:
若是第1类事件,则包含两个整数,依次是1,ci;
若是第2类事件,则包含五个整数,依次是2,ai,bi,ki,yi。
输出
输出若干行,每行一个整数,依次表示每个骑士休息的城堡编号。若骑士不可能休息,则输出 -1。
样例输入
3
0 1 2
5
2 1 3 1 0
1 2
2 1 3 1 0
2 1 3 1 1
2 1 3 1 2
样例输出
2
-1
-1
2
提示
【数据规模和约定】
20%的数据:1 ≤ N, M ≤ 1000;
另有30%的数据:有且仅有一个领主没有下属;
100%的数据:1 ≤ N, M ≤ 105,1 ≤ ai, bi, ci, ki ≤ N,0 ≤ yi < i, 每个事件中 ai ≠ bi。
来源
solution
树剖,转化为区间问题
对于每一个时间开一棵主席树,下标1~N,表示i是否被毁坏
对于询问,取出第y棵树和现在的树
如果有变动,就不能住。
求第k大就在线段树上二分(就是主席树经典操作)
比较烦的就是从b到lca的路径要求top-k+1大,
因为它是倒过来的
还有ab不能住,需要加一加
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
using namespace std;
int n,m,head[maxn],t1,t2,tot,dfn[maxn],deep[maxn],son[maxn],size[maxn];
int top[maxn],fa[maxn],sc,total,dy[maxn],op,root[maxn],t,a,b;
int lca,a1,b1,li,ri,rk,las,rak,num1,num2,ff;
struct no{
int ls,rs,x;
}tree[maxn*23];
struct node{
int v,nex;
}e[maxn*2];
void lj(int t1,int t2){
total++;e[total].v=t2;e[total].nex=head[t1];head[t1]=total;
}
void dfs1(int k,int fath){
fa[k]=fath;deep[k]=deep[fath]+1;
int gp=-1,sz=0;
for(int i=head[k];i;i=e[i].nex){
if(e[i].v!=fath){
dfs1(e[i].v,k);
if(gp==-1)gp=e[i].v;
if(size[e[i].v]>size[gp])gp=e[i].v;
sz+=size[e[i].v];
}
}
size[k]=sz+1;son[k]=gp;
}
void dfs2(int k){
dfn[k]=++sc;dy[sc]=k;
if(son[k]!=-1){
top[son[k]]=top[k];
dfs2(son[k]);
}
for(int i=head[k];i;i=e[i].nex){
if(e[i].v!=fa[k]&&e[i].v!=son[k]){
top[e[i].v]=e[i].v;
dfs2(e[i].v);
}
}
}
void wh(int k){
tree[k].x=tree[tree[k].ls].x+tree[tree[k].rs].x;
}
void dfs(int &k,int la,int l,int r,int pl){
k=++tot;
if(l==r){
tree[k].x=tree[la].x+1;return;
}
tree[k].ls=tree[la].ls,tree[k].rs=tree[la].rs;
int mid=l+r>>1;
if(pl<=mid)dfs(tree[k].ls,tree[la].ls,l,mid,pl);
else dfs(tree[k].rs,tree[la].rs,mid+1,r,pl);
wh(k);
}
int ch(int k,int la,int l,int r){
//cout<<l<<' '<<r<<' '<<li<<' '<<ri<<endl;
if(l>=li&&r<=ri){
int tmp=(r-l+1)-(tree[k].x-tree[la].x);
return tmp;
}
int mid=l+r>>1;
int su=0;
if(li<=mid)su+=ch(tree[k].ls,tree[la].ls,l,mid);
if(ri>mid)su+=ch(tree[k].rs,tree[la].rs,mid+1,r);
return su;
}
int ask(int k,int la,int l,int r,int fs){
//cout<<l<<' '<<r<<' '<<li<<' '<<ri<<endl;
if(l==r)return dy[l];
int mid=l+r>>1;
if(ri>mid){
int hh=ch(tree[k].rs,tree[la].rs,mid+1,r);
if(hh>=fs)return ask(tree[k].rs,tree[la].rs,mid+1,r,fs);
else return ask(tree[k].ls,tree[la].ls,l,mid,fs-hh);
}
else return ask(tree[k].ls,tree[la].ls,l,mid,fs);
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&t1);
if(t1==0)continue;
lj(i,t1);lj(t1,i);
}
dfs1(1,0);top[1]=1;dfs2(1);
cin>>m;
for(int i=1;i<=m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d",&t);
dfs(root[i],root[i-1],1,n,dfn[t]);
}
else {
root[i]=root[i-1];
int num=0;
scanf("%d%d%d%d",&a,&b,&rk,&las);
li=ri=dfn[a];ff=rk;
rk+=ch(root[i],root[las],1,n);
li=ri=dfn[b];
int fsy=0;
fsy=ch(root[i],root[las],1,n);
t1=top[a],t2=top[b];
a1=a;b1=b;
while(t1!=t2){
if(deep[t1]<deep[t2])swap(t1,t2),swap(a,b);
li=dfn[t1],ri=dfn[a];
num+=ch(root[i],root[las],1,n);
a=fa[t1],t1=top[a];
}
if(deep[a]<deep[b])swap(a,b);
lca=b;
li=dfn[b],ri=dfn[a];
num+=ch(root[i],root[las],1,n);//cout<<"haha "<<rk<<' '<<num<<' '<<rak<<" "<<ff<<" "<<fsy<<endl;
if(num-fsy<rk){puts("-1");continue;}
rak=num-rk+1;
// left
a=a1;t1=top[a];
bool fl=0;
while(t1!=top[lca]){
li=dfn[t1],ri=dfn[a];
num=ch(root[i],root[las],1,n);
if(num>=rk){
printf("%d\n",ask(root[i],root[las],1,n,rk));
fl=1;break;
}
else rk-=num;
a=fa[t1],t1=top[a];
}
if(fl)continue;
li=dfn[lca],ri=dfn[a];
num=ch(root[i],root[las],1,n);
if(num>=rk){
int ans=ask(root[i],root[las],1,n,rk);
if(ans==b1)puts("-1");
else printf("%d\n",ans);
continue;
}
// right
fl=0;rk=rak;
b=b1,t2=top[b];
while(t2!=top[lca]){
li=dfn[t2],ri=dfn[b];
num=ch(root[i],root[las],1,n);
if(num>=rk){
printf("%d\n",ask(root[i],root[las],1,n,rk));
fl=1;break;
}
else rk-=num;
b=fa[t2],t2=top[b];
}
if(fl)continue;
li=dfn[lca],ri=dfn[b];
num=ch(root[i],root[las],1,n);
if(num>=rk){
int ans=ask(root[i],root[las],1,n,rk);
if(ans==a1)puts("-1");
else printf("%d\n",ans);
continue;
}
}
}
return 0;
}
树上路径(path)的更多相关文章
- 【BZOJ3784】树上路径
题目大意 给定一个\(N\)个结点的树,结点用正整数\(1..N\)编号.每条边有一个正整数权值.用\(d(a,b)\)表示从结点\(a\)到结点\(b\)路边上经过边的权值.其中要求\(a < ...
- ASP.NET中的路径(path) 详解
一 ASP.NET常用路径(path)获取方法与格式对照表 假设我们的网址为http://localhost:1897/ News/Press/Content.aspx?id=1019 跟 Brows ...
- 网站发布出现“未能找到路径“path\bin\roslyn\csc.exe”....“和拒绝访问的解决办法
最近在2017上新建了一个MVC项目,发布是出现了各种奇怪的问题,其中一个错误是: 未能找到路径“path\bin\roslyn\csc.exe”.... 经过网上搜寻资料发现罪魁祸首就是NUGET里 ...
- SVG路径PATH
SVG路径PATH 在使用之前建议下个PS或者FLASH玩玩里面的钢笔工具(FLASH里的钢笔工具比PS里的好用) PATH用到的指令: M----(X Y):移动到 Z----(none):关闭路径 ...
- SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- SVG 学习<七> SVG的路径——path(1)直线命令、弧线命令
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- hihocoder[Offer收割]编程练习赛19 D 相交的铁路线(树上路径交)
傻逼题... 裸的树上路径交 两条树上的路径$[a,b]$和$[c,d]$有交,则有$lca(a,b)$在$[c,d]$上或$lca(c,d)$在$[a,b]$上. 其实只要深度大的$lca$在另一条 ...
- 某模拟赛C题 树上路径统计 (点分治)
题意 给定一棵有n个节点的无根树,树上的每个点有一个非负整数点权.定义一条路径的价值为路径上的点权和-路径上的点权最大值. 给定参数P,我!=们想知道,有多少不同的树上简单路径,满足它的价值恰好是P的 ...
- 【JZOJ4715】【NOIP2016提高A组模拟8.19】树上路径
题目描述 给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E.(k为路径p上的边的权值和) 输入 第一行给出N,S,E.N代表树的点数,S,E如题目描述. 下面N- ...
随机推荐
- java算法面试题:从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序 ;读取docx 读取doc 使用poi 相关jar包提集提供下载
从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序 1,张三,28 2,李四,35 3,张三,28 4,王五,35 5,张三,28 6,李四,35 7,赵六,28 ...
- Oracle数据库学习(一)
Oracle数据库由甲骨文公司开发,是基于对象的关系型数据库:下面是简单的学习数据库操作等知识. 1.SQL单表查询(设一个表名为tab) (1)查询所有记录 select * from tab(一般 ...
- SpringBoot AOP综合例子
完整源码:https://github.com/947133297/cgLibDemo 通过AOP来便捷地输出日志,能更加方便排查系统的bug,这个例子中简单输出自定义文件和函数执行时的参数,函数要不 ...
- eclipse projectExplorer视图(以包的方式显示)与navigator视图切换(以文件夹的方式显示)及树状视图与平面视图的切换
projectExplorer与navigator的切换 projectExplorer视图效果 想要此视图效果步骤如下: 分割------------------------------------ ...
- HDU 6153 KMP
最终刷KMP目标就是为了挑战这道题!现在成功了恩... 首先,题目大意是:给出一个字符串str1,之后给出另一个字符串str2,问,str2的后缀在str1匹配的次数*后缀当前长度是多少 首先考虑正统 ...
- Kubernetes master服务定制编译docker镜像
前言 之前部署了Kubernetes 1.13.0,发现master服务的启动方式与1.10.4版本有所区别,kube-apiserver.kube-controller-manager和kube-s ...
- SharedPreferences使用(通过键值保存数据)
保存数据到SharedPreferences中 要想使用SharedPreferences来存储数据, 首先需要获取到SharedPreferences对象. Android中主要提供了三种方法用于得 ...
- 菜鸟学Linux - Hard Link与Symbolic Link
在学习Hard Link与Symbolic Link之前,需要大概了解一下inode与data block.在Linux的文件系统中,一个文件对应一个inode与若干个data block.inode ...
- Jconsole连接Tomcat JVM
修改java虚拟机启动参数 在%TOMCAT_HOME%\bin\catalina.sh文件的最顶端 JAVA_OPTS=”-Dcom.sun.management.jmxremote.port=10 ...
- Redis实现之服务器
命令请求的执行过程 一个命令请求从发送到获得回复的过程中,客户端和服务器需要完成一系列操作.举个栗子,如果我们使用客户端执行以下命令: 127.0.0.1:6379> SET KEY VALUE ...