CF983E NN country

news/2024/12/2 19:46:13/

NN country

题目描述
传送门:http://codeforces.com/contest/983/problem/E

题解
首先有一个很显然的贪心策略,我们对于每个节点预处理出从它出发向上乘一次车最远能到哪。
对于一次询问,两个点x,y,我们先让这两个点贪心地往lca方向跑。
这样x点跑了a次到了lx点,y点跑了b次到了rx点。
如果lx到rx可以乘一次车到达,那么答案是a+b+1,否则答案就是a+b+2。
所以问题就转化成了给两个点x,y,询问它们的子树中是否存在可以直达的路径。
一种暴力办法是直接上树套树,树状数组套个set就好了,题目时限3秒,在cf上应该能过。
考虑少一个log的做法。
我们对于一组点lx,rx,它们对应的dfs序区间是 [L[lx],R[lx]] 和 [L[rx],R[rx]]。
先dfs一遍这棵树,对于每条巴士线路,当访问到它的起点的时候,将它的终点赋上权值。
如果我们将 [L[lx],R[lx]] 区间内出发的路径所对应的终点的权值扣回去之后 [L[rx],R[rx]] 的权值和扣回去之前不一样那么就存在一条可以直达的路径。
在写的时候,我们按dfs序跑一遍,一边跑一边修改。
我们在访问到L[lx]-1 和 R[lx]的时候分别求一下 [L[rx],R[rx]]的值,把它们相减判断一下就好了。
区间和拿个树状数组搞搞就好了。

代码

#include<bits/stdc++.h>
#define N 200005
#define D 18
using namespace std;
int n,m,Q,f[N][D+1],w[N][D+1],g[N],sum[N],ans[N];
int k,la[N],ff[N*2],dep[N],L[N],R[N],cnt,c[N];
struct node{int a,b;}e[N*2];
vector<node>q[N];
vector<int>t[N],h[N];
void add(int a,int b)
{e[++k]=(node){a,b};ff[k]=la[a];la[a]=k;e[++k]=(node){b,a};ff[k]=la[b];la[b]=k;
}class bit
{public:void modify(int x,int val){for(;x<=n;x+=x&-x)c[x]+=val;}int qry(int x){int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
}T;void dfs1(int x)
{L[x]=++cnt;for(int i=1;i<=D;i++)w[x][i]=w[w[x][i-1]][i-1];for(int a=la[x];a;a=ff[a])if(e[a].b!=w[x][0])dep[e[a].b]=dep[x]+1,dfs1(e[a].b);R[x]=cnt;
}void dfs2(int x)
{g[x]=x;for(int i=0;i<h[x].size();i++)if(dep[h[x][i]]<dep[g[x]])g[x]=h[x][i];for(int a=la[x];a;a=ff[a])if(e[a].b!=w[x][0]){dfs2(e[a].b);if(dep[g[e[a].b]]<dep[g[x]])g[x]=g[e[a].b];}f[x][0]=g[x];
}void prepare()
{for(int j=1;j<=D;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
}int lca(int x,int y)
{if(dep[x]<dep[y])swap(x,y);for(int i=D;i>=0;i--)if(dep[w[x][i]]>=dep[y])x=w[x][i];if(x==y)return x;for(int i=D;i>=0;i--)if(w[x][i]!=w[y][i])x=w[x][i],y=w[y][i];return w[x][0];
}node work(int x,int pos)
{if(x==pos)return (node){x,0};int res=0;for(int i=D;i>=0;i--)if(dep[f[x][i]]>dep[pos])x=f[x][i],res+=(1<<i);if(f[x][0]==x)return (node){x,-1};return (node){x,res};
}int main()
{int x,y,id,inv,pos;node A,B;scanf("%d",&n);for(int i=2;i<=n;i++)scanf("%d",&w[i][0]),add(w[i][0],i);dep[1]=1;dfs1(1);scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);pos=lca(x,y);if(L[x]>L[y])swap(x,y);t[L[x]].push_back(L[y]);if(dep[pos]<dep[x])h[x].push_back(pos);if(dep[pos]<dep[y])h[y].push_back(pos);}scanf("%d",&Q);dfs2(1);prepare();for(int i=1;i<=Q;i++){scanf("%d%d",&x,&y);pos=lca(x,y);A=work(x,pos);B=work(y,pos);if(A.b==-1||B.b==-1){ans[i]=-1;continue;}if(x==pos||y==pos){ans[i]=A.b+B.b+1;continue;}ans[i]=A.b+B.b+2;x=A.a;y=B.a;if(L[x]>L[y])swap(x,y);q[L[x]-1].push_back((node){y,-i});q[R[x]].push_back((node){y,i}); }for(int i=1;i<=n;i++){for(int j=0;j<t[i].size();j++)T.modify(t[i][j],1);for(int j=0;j<q[i].size();j++){inv=(q[i][j].b>0?1:-1);x=q[i][j].a;id=q[i][j].b*inv;sum[id]+=inv*(T.qry(R[x])-T.qry(L[x]-1)); }}for(int i=1;i<=Q;i++)printf("%d\n",ans[i]-(sum[i]>0));return 0;
} 

http://www.ppmy.cn/news/170136.html

相关文章

Spartan6 LX45 DDR3调试与分析

新的一年&#xff0c;新的开始。本文对最近的学习做个总结吧。最近在做spartan6的ddr3开发&#xff0c;FPGA采用的是spartan6的XC6LX45T&#xff0c;平台工具为ISE14.6&#xff0c;MIG的版本为3.92。采用的DDR3芯片为MT41J128M16XX-187E&#xff0c;并使用chipscope完成仿真调试…

linux主机风扇速度控制 解决记录 it8613E z490 GTN ubuntu 20.04

OS: ubuntu 20.04、主板&#xff1a;biostar z490 GTN、风扇IO芯片&#xff1a;it8613E lmsensors 可以获取 温度传感器 与 风扇的转速&#xff0c;也可以自定义调整风扇速度。 1、运行sensors-detect显示it8613E无驱动&#xff08;如图&#xff09; it8613E不是一个新的芯片…

SY6982E芯片了解

一、芯片基本描述 1.SY6982E是一款3.6-5.5VIN&#xff0c;2A两节电池的同步升压锂离子电池充电芯片。 2.集成1MHz开关频率和全面保护功能。 3.充电电流高达2A可以通过使用外部电阻器来设置不同的便携式应用&#xff0c;并同时指示充电器电流信息。 4.具有用于安全电池充电操…

华硕P8Z77-V LX老主板转换卡升级NVMe M2硬盘经验,老主机的福音,质的飞跃

每年双十一都是淘货升级老家伙的时候&#xff0c;今年也不例外&#xff0c;随着日子长久&#xff0c;软件的增多&#xff0c;虽然已经尽量装在系统盘以外的盘&#xff0c;但C盘还是日渐不够用&#xff0c;从以前的30G系统盘升到60G&#xff0c;60G升到100G&#xff0c;C盘永远不…

mcd, lm, VS lx

LED常识之 mcd&lm&w的关系 转载自&#xff1a; http://1198.vip.blog.163.com/blog/static/202177117201211624535412/ LED 亮度是指发光体&#xff08;反光体&#xff09;表面发光&#xff08;反光&#xff09;强弱的物理量。人眼从一个方向观察光源&#xff0c;在…

ML302 GPIO模拟SPI适配LX12864T5B屏

1.背景说明 最近在搞一个DTU 的小项目&#xff0c;使用的是中移动的ML302&#xff0c;关于ML302的相关资料&#xff0c;在中移动的官网&#xff08;http://iot.10086.cn 、http://onemo10086.com&#xff09;上就有很多教程&#xff0c;而且配套的openCPU SDK里面也有相关的de…

(Lx)Linux 实验

Linux 实验 文章目录 Linux 实验实验2 Red Hat 的使用&#xff08;二&#xff09;实验3 Red Hat 的使用&#xff08;三&#xff09;实验4 Red Hat 的操作&#xff08;四&#xff09;实验5 vi 编辑器、磁盘管理和文件系统实验6 用户账户管理实验7 软件包管理实验8 网络基本配置实…

c语言中e什么作用是什么,c语言中%e是什么意思

满意答案 yeye_pig 2019.11.25 采纳率&#xff1a;40% 等级&#xff1a;9 已帮助&#xff1a;614人 c语言%e的意思是&#xff1a;以指数形式输出实数。 指针的值是语言实现(编译程序)相关的&#xff0c;但几乎所有实现中&#xff0c;指针的值都是一个表示地址空间中某个存储…