[Codeforces 226E]Noble Knight's Path
题目大意:
有一棵n个节点的树,m年。初始每个节点都有。每天有如下操作:
1. 给定c,让c没有(c只可能没有一次)。
2. 给定s,t,k,y,求从第y+1年到现在(即忽略y+1年之前的操作1),s到t的路径上第k个有的节点(不存在输出-1)。
解题思路:
首先树链剖分,然后对每天建主席树。我们把有设为1,没有设为0。
则操作1就是单点修改,直接改即可。
操作2,我们把整条路径拆成s到lca和lca到t,两边分开考虑。
对于s到lca的路径,让s沿着链往上跳,同时进行区间查询。若区间里的点已经大于等于k,则答案一定在这个区间内。
对于lca到t的路径,相当于要找的是t到lca上第(路径上有的点总数-k+1)个有的点,则和上面的方法一样。
那么我们假设已经知道了答案所在区间,如何求答案呢?其实相当于在一个01序列里查询某个区间倒数(从下往上dfs序递减)第k个1的位置,我们把[l,r]区间补成[l,n]区间,然后相当于整棵线段树上查询。
最后一个问题,如何处理在y+1之前没有的点。
我们发现,从第y棵主席树到当前的主席树,对应节点如果有变化,则一定是在y+1到现在才没有的。所以主席树上做差即可求出没有的点的个数,有的也能求了。
时间复杂度\(O(n\log^2 n)\)。
C++ Code:
#include<bits/stdc++.h>
const int N=100005;
int n,fa[N],rt,cnt=0,sz[N],son[N]={0},top[N],dep[N],idx=0,Q,dfn[N],head[N],hq[N],nodes=0,year[N];
int ret,L,R;
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
struct edge{
int to,nxt;
}e[N<<1];
struct SegmentTreeNode{
int v,ls,rs,l,r,sz;
}d[N<<5];
void BigMagician(int now){
sz[now]=1;
for(int i=head[now];i;i=e[i].nxt)
if(fa[e[i].to]==now){
dep[e[i].to]=dep[now]+1;
BigMagician(e[i].to);
sz[now]+=sz[e[i].to];
if(!son[now]||sz[e[i].to]>sz[son[now]])son[now]=e[i].to;
}
}
void dfs(int now){
dfn[now]=++idx;hq[idx]=now;
if(son[now])top[son[now]]=top[now],dfs(son[now]);
for(int i=head[now];i;i=e[i].nxt)
if(dep[now]<dep[e[i].to]&&e[i].to!=son[now])
dfs(top[e[i].to]=e[i].to);
}
void build(int l,int r,int&o){
o=++nodes;
d[o].l=l,d[o].r=r,d[o].sz=r-l+1;
if(l==r)d[o].v=1;else{
int mid=l+r>>1;
build(l,mid,d[o].ls);
build(mid+1,r,d[o].rs);
d[o].v=d[d[o].ls].v+d[d[o].rs].v;
}
}
void modify(int o,int&nw,int&p){
d[nw=++nodes]=d[o];
--d[nw].v;
if(d[o].l!=d[o].r){
int mid=d[o].l+d[o].r>>1;
if(p<=mid)modify(d[o].ls,d[nw].ls,p);else
modify(d[o].rs,d[nw].rs,p);
}
}
void query(int&o,int&nw){
if(L<=d[o].l&&d[o].r<=R)ret+=d[o].v-d[nw].v;else{
int mid=d[d[o].ls].r;
if(L<=mid)query(d[o].ls,d[nw].ls);
if(mid<R)query(d[o].rs,d[nw].rs);
}
}
void query2(int&o,int&nw,int k){
if(d[o].l==d[o].r)ret=hq[d[o].l];else{
if(k<=d[d[o].rs].sz-d[d[o].rs].v+d[d[nw].rs].v)query2(d[o].rs,d[nw].rs,k);else
query2(d[o].ls,d[nw].ls,k-(d[d[o].rs].sz-d[d[o].rs].v+d[d[nw].rs].v));
}
}
inline int theLCA(int x,int y){
for(;top[x]!=top[y];)
if(dep[top[x]]>=dep[top[y]])x=fa[top[x]];else
y=fa[top[y]];
return(dep[x]<dep[y])?x:y;
}
inline int search_to_lca(int u,int v,int&k,int&y,int&nw){
while(top[u]!=top[v]){
ret=0;
L=dfn[top[u]],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
if(ret>=k){
ret=0;
L=dfn[u]+1,R=n;
if(L<=n)
query(y,nw);
ret=R-L+1-ret;
k+=ret;
ret=0;
query2(y,nw,k);
return ret;
}
k-=ret;
u=fa[top[u]];
}
ret=0;
L=dfn[v],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
if(ret>=k){
ret=0;
L=dfn[u]+1,R=n;
if(L<=n)
query(y,nw);
ret=R-L+1-ret;
k+=ret;
ret=0;
query2(y,nw,k);
return ret;
}
k-=ret;
return -1;
}
inline int search_on_a_list(int u,int v,int&y,int&nw){
int ans=0;
while(top[u]!=top[v]){
ret=0;
L=dfn[top[u]],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
ans+=ret;
u=fa[top[u]];
}
ret=0;
L=dfn[v],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
return ans+ret;
}
inline int search_from_lca(int u,int v,int&k,int&y,int&nw){
int all=search_on_a_list(u,v,y,nw);
if(all<k)return -1;
k=all-k+1;
while(top[u]!=top[v]){
ret=0;
L=dfn[top[u]],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
if(ret>=k){
ret=0;
L=dfn[u]+1,R=n;
if(L<=n)
query(y,nw);
ret=R-L+1-ret;
k+=ret;
ret=0;
query2(y,nw,k);
return ret;
}
k-=ret;
u=fa[top[u]];
}
ret=0;
L=dfn[v],R=dfn[u];
query(y,nw);
ret=R-L+1-ret;
if(ret>=k){
ret=0;
L=dfn[u]+1,R=n;
if(L<=n)
query(y,nw);
ret=R-L+1-ret;
k+=ret;
ret=0;
query2(y,nw,k);
return ret;
}
k-=ret;
return -1;
}
int main(){
// freopen("travel.in","r",stdin);
// freopen("travel.out","w",stdout);
memset(head,0,sizeof head);
n=readint();
for(int i=1;i<=n;++i){
fa[i]=readint();
if(!fa[i])rt=i;else{
e[++cnt]=(edge){i,head[fa[i]]};
head[fa[i]]=cnt;
e[++cnt]=(edge){fa[i],head[i]};
head[i]=cnt;
}
}
dep[rt]=1;
top[rt]=rt;
BigMagician(rt);
dfs(rt);
build(1,n,year[0]);
Q=readint();
for(int i=1;i<=Q;++i){
int opt=readint();
if(opt==1){
int p=readint();
modify(year[i-1],year[i],dfn[p]);
}else{
year[i]=year[i-1];
int u=readint(),v=readint(),k=readint(),y=readint();
ret=0;
L=R=dfn[u];
query(year[y],year[i]);
if(!ret)++k;
int lca=theLCA(u,v);
int ans=search_to_lca(u,lca,k,year[y],year[i]);
if(!~ans){
ret=0;
L=R=dfn[lca];
query(year[y],year[i]);
if(!ret)++k;
ans=search_from_lca(v,lca,k,year[y],year[i]);
}
if(ans==v||ans==u)ans=-1;
printf("%d\n",ans);
}
}
return 0;
}
[Codeforces 226E]Noble Knight's Path的更多相关文章
- [CF226E]Noble Knight's Path
[CF226E]Noble Knight's Path 题目大意: 一棵\(n(n\le10^5)\)个结点的树,初始时所有结点都是白色.\(m(m\le10^5)\)次操作,操作包含以下两种: 将点 ...
- CF226E Noble Knight's Path/bzoj4704 旅行
题目描述: bz luogu 题解: 主席树维护大力树剖. 一条路径上不允许过的点的个数是当前袭击数-$y$时袭击数, 所以允许经过的点的个数是总数-当前袭击数+$y$时袭击数. 用主席树去维护每个时 ...
- Lintcode: Knight Shortest Path
Given a knight in a chessboard (a binary matrix with 0 as empty and 1 as barrier) with a source posi ...
- Educational Codeforces Round 17 D. Maximum path DP
题目链接:http://codeforces.com/contest/762/problem/D 多多分析状态:这个很明了 #include<bits/stdc++.h> using na ...
- codeforces 388B Fox and Minimal path
这个题目的突破口就是固定最短长度,然后以二进制的形式分层: 最后把需要的曾连起来: #include<cstdio> #include<cstring> #define max ...
- 【Codeforces 242C】King's Path
[链接] 我是链接,点我呀:) [题意] 让你找到(x0,y0)到(x1,y1)的一条最短路 走过的点必须在所给的n个横向路径上 [题解] 因为n条横向路径上的点最多不会超过10的5次方个,所以我们可 ...
- 【Codeforces 356A】Knight Tournament
[链接] 我是链接,点我呀:) [题意] n个人矩形m场比赛 每场比赛由编号为li~ri且之前没有被淘汰的人进行. 已知第i场的winner是xi winner会把这一场其他所有的人都淘汰. 问你n个 ...
- The Sorrows of Young Werther
The Sorrows of Young Werther J.W. von Goethe Thomas Carlyle and R.D. Boylan Edited by Nathen Haskell ...
- 九章lintcode作业题
1 - 从strStr谈面试技巧与代码风格 必做题: 13.字符串查找 要求:如题 思路:(自写AC)双重循环,内循环读完则成功 还可以用Rabin,KMP算法等 public int strStr( ...
随机推荐
- Bash中文速查表
最好用的中文速查表(Cheatsheet) 来源:https://github.com/skywind3000/awesome-cheatsheets 感谢网友们的贡献! ############## ...
- Linux 中常用的基础命令二
1.Linux文件分层结构 FHS:Linux有一个组织叫LSB定义的Linux发行版基础目录名称命名法则及功用规定,这种标准叫FHS文件系统层级标准./bin 存放可执行的二进制程序,管理员和 ...
- Python Django log日志
log日志 log开发日志 一.创建项目 1.python -m venv ll_env # 创建虚拟环境 2.source ll_env/bin/activate # 激活虚拟环境 3.pip in ...
- Centos6.5安装Seafile,遇到的问题处理记录。
问题1:启动Seafile安装脚本时,提示找不到MySQL-python模块,使用yum安装成功也提示未安装该软件包 问题1解决方法:需要通过 python 的工具pip来安装MySQL-python ...
- 【codeforces 723E】One-Way Reform
[题目链接]:http://codeforces.com/contest/723/problem/E [题意] 给你一个无向图; 让你把这m条边改成有向图; 然后使得出度数目等于入度数目的点的数目最多 ...
- RobotFrameWork+APPIUM实现对安卓APK的自动化测试----第五篇【AppiumLibrary校验函数介绍】
http://blog.csdn.net/deadgrape/article/details/50619050 以上连作者先跪一下方便面,在上一篇中,作者遗漏了两个常用的函数: 1.长按 Long P ...
- BA-通讯总线-百通1419a和9841
百通1419A线缆的简单介绍: Belden1419A- Belden电缆线1419A 多股导体—低容计算机电缆 FOR EIA RS-232/422 Belden 1419A是24 AWG(7*32 ...
- BA--冷源系统原理图解
- 关于部门后端所有转向java前初步设想
Java服务有些什么形式?眼下来看主要是下面几类: 1. 执行在Web应用server的Servlet 2. Thrift.PB.Avro等相似框架写的java服务 3. WebService( ...
- HTML5 格式化方式以及应用
<b>加粗字体 <big>定义大号字体 <em>定义着重文字 <i>定义斜体字 <small>定义小号字体 <strong>定义 ...