Codeforces983E. NN country
新鲜出炉!
$n \leq 200000$的树,给$m \leq 200000$条链,$q \leq 200000$个询问,每次问一条询问链最少用m条中的几条给定链覆盖其所有边,可能无解。
首先确定一种贪心策略:$low_x$表示$x$能通过一条链跳到的最高的点(这里吐槽一下,题解描述时的树是反过来的,树根在地上!反人类啊,然后他后面所有的“高”“矮”描述全是反过来的!!!无良出题人),假设询问俩点$u,v$,lca即为$t$,那么先从$u$一直沿着$low$跳到$t$下面一点点,$v$一直沿着$low$跳到$t$下面一点点,这样的步数分别为$a$和$b$,然后答案为$a+b+2$或者$a+b+1$,取决于最后跳到那俩点是否能在一条链上。$low$的计算dfs一次就行(我TM还跑去看代码了),建出$low$的st表之后上面操作可以倍增出,现在开始$v$和$u$表示他们最后跳到比$t$下面一点点的那俩点。
现在问:一棵树好多链,每次问一个点对有没有可能在一条链上。
这不是二维数点嘛hhh,dfs序搞出来,然后如果两个询问点子树内有同个链的端点,那就存在。dfs搜一遍(第一维),搜一个点之后,先查询下他对应的另一询问点的子树(第二维),然后把这个点上的“链端点”加到树状数组,然后搜子树(第一维),然后回来再查一次另一询问点的子树(第二维),看两次查的一不一样。
//#include<iostream>
#include<cstring>
#include<cstdio>
//#include<time.h>
//#include<complex>
//#include<set>
//#include<queue>
#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std; #define LL long long
int qread()
{
char c; int s=,f=; while ((c=getchar())<'' || c>'') (c=='-') && (f=-);
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*f;
} //Pay attention to '-' , LL and double of qread!!!! int n,m,lq;
#define maxn 200011
struct Edge{int to,next;}edge[maxn<<]; int first[maxn],le=;
void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;} int top[maxn],dep[maxn],fa[maxn],size[maxn],ll[maxn],rr[maxn],Time=,hea[maxn];
void dfs1(int x)
{
size[x]=; hea[x]=; Time++; ll[x]=Time;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i];
fa[e.to]=x; dep[e.to]=dep[x]+; dfs1(e.to); size[x]+=size[e.to];
if (size[hea[x]]<size[e.to]) hea[x]=e.to;
}
rr[x]=Time;
}
void dfs2(int x,int tt)
{
top[x]=tt;
if (hea[x]) dfs2(hea[x],tt);
for (int i=first[x];i;i=edge[i].next) if (edge[i].to!=hea[x]) dfs2(edge[i].to,edge[i].to);
}
int lca(int x,int y)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y;
x=fa[top[x]];
}
if (dep[x]<dep[y]) return x; return y;
} int low[maxn][];
void dfslow(int x)
{
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; dfslow(e.to);
low[x][]=dep[low[x][]]<dep[low[e.to][]]?low[x][]:low[e.to][];
}
}
void makelow()
{
for (int j=;j<=;j++)
for (int i=;i<=n;i++)
low[i][j]=low[low[i][j-]][j-];
} struct Node{int x,y,t,ans;}a[maxn],q[maxn];
vector<int> va[maxn],vb[maxn];
void ina(int x,int y) {va[x].push_back(y);}
void inb(int x,int y) {vb[x].push_back(y);} int XX;
int find(int x,int t)
{
if (dep[low[x][]]>dep[t]) {XX=-0x3f3f3f3f; return -;}
if (x==t) {XX=-; return -;}
int ans=;
for (int j=;~j;j--) if (dep[low[x][j]]>dep[t]) x=low[x][j],ans|=(<<j);
XX=ans; return x;
} struct BIT
{
int n,a[maxn];
void clear(int N) {n=N;}
void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
int query(int x) {int ans=; for (;x;x-=x&-x) ans+=a[x]; return ans;}
}t;
int pp[maxn];
void dfs(int x)
{
for (int sz=vb[x].size(),i=;i<sz;i++)
{
int u=vb[x][i];
pp[u]=t.query(rr[q[u].y])-t.query(ll[q[u].y]-);
}
for (int sz=va[x].size(),i=;i<sz;i++)
{
int u=va[x][i];
if (x==a[u].x) t.add(ll[a[u].y],);
else t.add(ll[a[u].x],);
}
for (int i=first[x];i;i=edge[i].next) dfs(edge[i].to);
for (int sz=vb[x].size(),i=;i<sz;i++)
{
int u=vb[x][i];
if (t.query(rr[q[u].y])-t.query(ll[q[u].y]-)!=pp[u]) q[u].ans--;
}
} int main()
{
n=qread();
for (int i=,x;i<=n;i++) {x=qread(); in(x,i);}
dep[]=; dfs1(); dfs2(,); for (int i=;i<=n;i++) low[i][]=i;
m=qread();
for (int i=;i<=m;i++)
{
a[i].x=qread(); a[i].y=qread();
a[i].t=lca(a[i].x,a[i].y);
low[a[i].x][]=dep[low[a[i].x][]]<dep[a[i].t]?low[a[i].x][]:a[i].t;
low[a[i].y][]=dep[low[a[i].y][]]<dep[a[i].t]?low[a[i].y][]:a[i].t;
ina(a[i].x,i); ina(a[i].y,i);
}
dfslow(); makelow(); lq=qread();
for (int i=;i<=lq;i++)
{
q[i].x=qread(); q[i].y=qread();
q[i].t=lca(q[i].x,q[i].y);
q[i].ans=;
int x=find(q[i].x,q[i].t); q[i].ans+=XX;
int y=find(q[i].y,q[i].t); q[i].ans+=XX;
if (x> && y>) {q[i].x=x; q[i].y=y; inb(x,i);}
} t.clear(n);
dfs();
for (int i=;i<=lq;i++) printf("%d\n",q[i].ans<?-:q[i].ans);
return ;
}
Codeforces983E. NN country的更多相关文章
- 【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】983 E. NN country 树上倍增+二维数点
[题目]E. NN country [题意]给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖.\(n,m,q \leq 2*10^5\). [算法]树上倍增+二维数点(树状数组 ...
- cf983E NN Country (倍增+dfs序+树状数组)
首先可以求出从某点做$2^k$次车能到的最浅的点,这个只要dfs一下,把它的孩子能到的最浅的点更新过来就可以 然后倍增地往上跳,不能跳到lca的上面,记录坐车的次数ans 此时有三种情况(设最远能跳到 ...
- [CF983E]NN country
题意:给一棵树,有许多条巴士线路$(a_i,b_i)$(巴士在路径上每个点都会停车),多次询问从一点到另一点最少要坐多少次巴士 首先dfs一遍预处理出一个点向上坐$2^k$次巴士能到的最浅点,于是我们 ...
- CF983E NN country(倍增,差分)
题意 给定一棵树和若干条路线,每条路线相当于树上 x,y 之间的路径,途径路径上的每个点 给出若干个询问,每次询问从 u 到 v 至少需要利用几条路线 N,M,Q≤200000 题解 构建倍增数组g[ ...
- Codeforces 983E - NN country(贪心+倍增优化)
Codeforces 题面传送门 & 洛谷题面传送门 一道(绝对)偏简单的 D1E,但是我怕自己过若干年(大雾)忘了自己的解法了,所以过来水篇题解( 首先考虑怎么暴力地解决这个问题,不难发现我 ...
- Codeforces Round #483 (Div. 1) 简要题解
来自FallDream的博客,未经允许,请勿转载,谢谢. 为了证明一下我又来更新了,写一篇简要的题解吧. 这场比赛好像有点神奇,E题莫名是道原题,导致有很多选手直接过掉了(Claris 表演24s过题 ...
- 多校联训 DS 专题
CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...
- Abandoned country
Abandoned country Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
随机推荐
- Codeforces Round #316 (Div. 2) C Replacement 扫描法
先扫描一遍得到每个位置向后连续的'.'的长度,包含自身,然后在扫一遍求出初始的合并次数. 对于询问,只要对应位置判断一下是不是'.',以及周围的情况. #include<bits/stdc++. ...
- MIPS简单入门
What ‘s the MIPS? 汇编语言 汇编语言是一类语言的总称,因处理器不同,而对应的不同机器的指令集也不同,产生了很多种汇编语言. 目前最流行的是ARM,MIPS,x86.ARM用于大量的移 ...
- scss引入的问题
导入.sass或.scss文件 css有一个不太常用的特性,即@import 导入功能,它允许在一个css文件中导入其他css文件.然而,结果是只有执行到@import 规则时,浏览器才会去下载其他c ...
- 给我说说你能想到几种分布式session实现
附录: https://mp.weixin.qq.com/s/8Hh4j0CjfF5S8zM29JZl2w # 面试官心理分析 面试官问了你一堆 dubbo 是怎么玩儿的,你会玩儿 dubbo 就可以 ...
- Linux命令基础操作--vim 归档 压缩 分区 格式化 挂载 Innode
1 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) 使用 cat命令将查看的文件合并输出到/1.txt 这里的关键:定位到文件,如果后面加上/后被认为是目录 分为两步,先 ...
- WINDOWS-API:API函数大全
操作系统除了协调应用程序的执行.内存分配.系统资源管理外,同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务是一个函数),可以帮肋应用程序达到开启视窗.描绘图形.使用周边设备的目的,由 ...
- ios之UIWebView(2)
UIWebView是iOS sdk中一个最常用的控件.是内置的浏览器控件,我们可以用它来浏览网页.打开文档等等.这篇文章我将使用这个控件,做一个简易的浏览器.如下图: 我们创建一个Window-bas ...
- Sass 构建之 7-1模式
Sass 项目结构之7-1模式 7-1模式的结构:7个文件夹,1个文件. 基本上,你需要将所有的部件放进7个不同的文件夹和一个位于根目录的文件(通常用main.scss或者app.scss) 编译时会 ...
- nginx正则配置解释和fastadmin
参考:http://www.cnblogs.com/netsa/p/6383094.html 1 2 3 4 5 6 7 8 9 10 11 1.^: 匹配字符串的开始位置: 2. $:匹配字符串 ...
- js,jq,php使用正则方法
1.js使用正则表达式案例: <script> var str=”543535364565@qq.com”; var res=“/^\d*@(QQ|qq|136)\.(com|cn)$/” ...