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\) ...
随机推荐
- POJ 1950暴搜
思路: 暴力枚举好了..每回判断一下-- 用long long会超时 但是10^20会爆int... 不过仔细想一想 超过10^9的数肯定拼不回0啊-- 猥琐用int AC了 (当然可以打表 ) // ...
- android adb command
一.adb启动activity: $ adb shell$ am start -n {包(package)名}/{包名}.{活动(activity)名称} 如:启动浏览器 # am start -n ...
- Edge 浏览器
Edge浏览器设计理念 无法播放:https://edgewelcomecdn.microsoft.com/site/images/tabs/rs3/tabs_screen.acd367a2.mp4 ...
- sublime text3前端常用插件
安装Package Control 在安装插件之前,需要让sublime安装Package Control.打开Sublime Text的控制台,快捷键ctrl + ~,在控制台中输入以下代码. im ...
- vue 事件参数传$event打印当前组件
<template> <div class="hello"> <button v-on:click.once="getinfo($event ...
- collections模块-namedtuple
namedtuple -> 命名元组 这里的命名指的是对元组中元素的命名. 通过一个例子来看 import collections Person = collections.namedtuple ...
- 程序员之--C语言细节13(二维数组和指针,&*a[i][0]的理解,数组1[e]和e[1]非常可能你没见过)
主要内容:二维数组和指针.&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_C ...
- Gradle学习之自己定义属性
请通过下面方式下载本系列文章的Github演示样例代码: git clone https://github.com/davenkin/gradle-learning.git 在前面的文章中我们 ...
- zjnu(1181)——石子合并
这道题算是最简单的区间dp了..非常久之前写的,搞懂原理了就1A. 传送门:problem_id=1181">http://acm.zjnu.edu.cn/CLanguage/show ...
- Redis 存储图片 [base64/url/path]vs[object]
一.base64图片编解码 基本流程:从网络获取下载一张图片.然后base64编码,再base64解码,存到本地E盘根文件夹下. import java.awt.image.BufferedImage ...