CF983E NN country(倍增,差分)
题意
题解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N=;
const int D=;
struct node{
int a,b;
};
vector<int> road[N],h[N];
vector<node> q[N];
int n,m,t,fa[N][D+],w[N][D+],head[N],sum[N],ans[N],g[N];
int cnt,tot,dep[N],id[N],size[N],c[N];
int lowbit(int x){
return x&-x;
}
void update(int x){
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=;
}
}
int check(int x){
int tmp=;
for(int i=x;i>=;i-=lowbit(i)){
tmp+=c[i];
}
return tmp;
}
struct edge{
int to,nxt;
}e[N*];
void add(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs1(int u,int deep){
dep[u]=deep;
id[u]=++tot;
size[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u][])continue;
dfs1(v,deep+);
size[u]+=size[v];
}
}
void dfs2(int u){
g[u]=u;
// cout<<u<<"ksdjfksdf"<<endl;
for(int i=;i<h[u].size();i++){
// cout<<h[u][i]<<endl;
if(dep[h[u][i]]<dep[g[u]])g[u]=h[u][i];
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
// cout<<v<<" "<<fa[u][0]<<endl;
if(v==fa[u][])continue;
dfs2(v);
if(dep[g[v]]<dep[g[u]])g[u]=g[v];
}
w[u][]=g[u];
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=D;i>=;i--){
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
}
if(x==y)return x;
for(int i=D;i>=;i--){
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
}
return fa[x][];
}
node work(int x,int LCA){
if(x==LCA)return (node){x,};
int tmp=;
for(int i=D;i>=;i--)
if(dep[w[x][i]]>dep[LCA])x=w[x][i],tmp+=(<<i);
if(w[x][]==x)return (node){x,-};
return (node){x,tmp};
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&fa[i][]);
add(fa[i][],i);
add(i,fa[i][]);
}
dfs1(,);
for(int i=;i<=D;i++)
for(int j=;j<=n;j++){
fa[j][i]=fa[fa[j][i-]][i-];
}
scanf("%d",&m);
for(int i=;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
int c=lca(x,y);
// cout<<c<<endl;
if(id[x]>id[y])swap(x,y);
road[id[x]].push_back(id[y]);
if(dep[c]<dep[x])h[x].push_back(c);
if(dep[c]<dep[y])h[y].push_back(c);
}
dfs2();
for(int i=;i<=n;i++){
// cout<<g[i]<<endl;
}
for(int i=;i<=D;i++)
for(int j=;j<=n;j++){
w[j][i]=w[w[j][i-]][i-];
// cout<<w[j][i]<<endl;
}
scanf("%d",&t);
for(int i=;i<=t;i++){
int x,y;
scanf("%d%d",&x,&y);
int c=lca(x,y);
node A=work(x,c);
node B=work(y,c);
if(A.b==-||B.b==-){
ans[i]=-;
continue;
}
if(x==c||y==c){
ans[i]=A.b+B.b+;
continue;
}
ans[i]=A.b+B.b+;
x=A.a;
y=B.a;
if(id[x]>id[y])swap(x,y);
q[id[x]-].push_back((node){y,-i});
q[id[x]+size[x]-].push_back((node){y,i});
}
for(int i=;i<=n;i++){
for(int j=;j<road[i].size();j++)update(road[i][j]);
for(int j=;j<q[i].size();j++){
int num=(q[i][j].b>?:-);
int x=q[i][j].a;int y=q[i][j].b*num;
sum[y]+=num*(check(id[x]+size[x]-)-check(id[x]-));
}
}
for(int i=;i<=t;i++){
printf("%d\n",ans[i]-(sum[i]>));
}
return ;
}
CF983E NN country(倍增,差分)的更多相关文章
- cf983E NN Country (倍增+dfs序+树状数组)
首先可以求出从某点做$2^k$次车能到的最浅的点,这个只要dfs一下,把它的孩子能到的最浅的点更新过来就可以 然后倍增地往上跳,不能跳到lca的上面,记录坐车的次数ans 此时有三种情况(设最远能跳到 ...
- [CF983E]NN country
题意:给一棵树,有许多条巴士线路$(a_i,b_i)$(巴士在路径上每个点都会停车),多次询问从一点到另一点最少要坐多少次巴士 首先dfs一遍预处理出一个点向上坐$2^k$次巴士能到的最浅点,于是我们 ...
- 【CodeForces】983 E. NN country 树上倍增+二维数点
[题目]E. NN country [题意]给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖.\(n,m,q \leq 2*10^5\). [算法]树上倍增+二维数点(树状数组 ...
- 【codeforces 983E】NN country
Description In the NN country, there are n cities, numbered from 1 to n, and n−1 roads, connecting t ...
- Codeforces 983E - NN country(贪心+倍增优化)
Codeforces 题面传送门 & 洛谷题面传送门 一道(绝对)偏简单的 D1E,但是我怕自己过若干年(大雾)忘了自己的解法了,所以过来水篇题解( 首先考虑怎么暴力地解决这个问题,不难发现我 ...
- NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
原文链接https://www.cnblogs.com/zhouzhendong/p/9275606.html 题目传送门 - 洛谷P1600 题目传送门 - LOJ#2359 题目传送门 - Vij ...
- NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)
BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...
- Codeforces983E. NN country
新鲜出炉! $n \leq 200000$的树,给$m \leq 200000$条链,$q \leq 200000$个询问,每次问一条询问链最少用m条中的几条给定链覆盖其所有边,可能无解. 首先确定一 ...
- 多校联训 DS 专题
CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...
随机推荐
- win32编程 画图
void cDefense::DrawAll() { HDC hDc = GetDC(m_hWnd);//获取客户区窗口,如果该值为NULL,GetDC则获整个屏幕的窗口. HDC dcMem = C ...
- xBIM 基础09 WeXplorer 基本应用
系列目录 [已更新最新开发文章,点击查看详细] 在本教程中,将学习如何创建最基本和最直接的查看器. 除了展示建筑模型外,不做其他任何操作.它将只使用内置导航,但是不会对按钮做出事件响应. &l ...
- Caffe学习--Net分析
Caffe_Net 1.基本数据 vector<shared_ptr<Layer<Dtype> > > layers_; // 记录每一层的layer参数 vect ...
- 如何使easyui的datagrid 高度自适应
如何使easyui的datagrid 高度自适应? 最开始使用easyui的datagrid加载数据时,对其设置的高度都是固定值,数据较多时table表现为滚动条形式.某天,老大突然需要datagri ...
- Innodb中的事务隔离级别和锁的关系(转载)
nodb中的事务隔离级别和锁的关系 原文:https://tech.meituan.com/innodb-lock.html ameng ·2014-08-20 15:50 前言: 我们都知道事务的几 ...
- 紫书 习题 11-10 UVa 12264 (二分答案+最大流)
书上写的是UVa 12011, 实际上是 12264 参考了https://blog.csdn.net/xl2015190026/article/details/51902823 这道题就是求出一种最 ...
- Qt之QTemporaryFile
简述 QTemporaryFile类是操作临时文件的I/O设备. QTemporaryFile用于安全地创建一个独一无二的临时文件.临时文件通过调用open()来创建,并且名称是唯一的(即:保证不覆盖 ...
- IOS中UIImagePickerController中文界面问题
今天沈阳斌子,写IOS项目遇到一个调用照相机的问题,找到解决方法,高速攻克了拿给PM看,结果PM说程序调用的照相机不是中文的是英文的.必须改成中文.上网找到了方法.试用后好用拿出来和大家分享.方法例如 ...
- 【剑指Offer学习】【面试题47:不用加减乘除做加法】
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+.-.×.÷四则运算符号. 解题思路 5 的二进制是101, 17 的二进制是10001 .还是试着把计算分成三步:第一步各位相加但不计进位. ...
- 我是怎么利用微信做兼职月入1W的
物价上涨.导致非常多人都感觉如今的收入入不敷出,有的是迫于生活压力.有的是为了提高生活质量,等等都想好好利用业余时间来做点兼职,当然我也不例外.正好笔者在微信刚推出一段时间的时候利用微信来做点兼职赚点 ...