解析

算法一

定义 upx,kup_{x,k}upx,k​ 为节点 xxx 从自己的颜色所在位置在返祖链上往后跳 2k2^k2k 个颜色到达的节点。
可以像倍增一样的求解。
这样对于一次询问 (s,t)(s,t)(s,t) 我们就能求出 (s,lca)(s,lca)(s,lca) 这一段能取到哪里了。
对于向下的情况,再处理一个 upx,k′up'_{x,k}upx,k′​ 表示节点 xxx 从自己的颜色所在位置在返祖链上往跳 2k2^k2k 个颜色到达的节点。
然后二分每一个询问的答案,从答案开始往前跳,看能否与 (s,lca)(s,lca)(s,lca) 相接即可判定是否合法。
时间复杂度 O(nlog⁡n+mlog⁡Clog⁡n)O(n\log n+m\log C\log n)O(nlogn+mlogClogn)。

算法二

考虑优化后一段 (lca,t)(lca,t)(lca,t) 的过程。
假设询问 iii 在 (s,lca)(s,lca)(s,lca) 过程中跳到了颜色 ccc,就在 lcalcalca 处增加一个 (i,c)(i,c)(i,c) 的元素,在 ttt 处打一个 (i)(i)(i) 标记。
考虑我们 dfsdfsdfs 过程中需要维护什么:

  1. 插入二元组 (i,c)(i,c)(i,c)
  2. 如果当前节点颜色为 ccc,收集器上的下一个颜色为 sufsufsuf,就使所有 (i,c)→(i,suf)(i,c)\to(i,suf)(i,c)→(i,suf)。
  3. 查询当前的 iii 元素的特征值。
  4. 撤销当前dfs的影响。

这个东西可以用可撤销并查集维护。
总复杂度 O(nlog⁡n+mlog⁡n)O(n\log n+m\log n)O(nlogn+mlogn)

代码

写的是算法二。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;const int N=2e6+100;
const int M=50050;
const int mod=1e9+7;
const double eps=1e-9;inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m,C,Mx;struct node{int to,nxt;
}e[N<<1];
int fi[N],cnt;
inline void addline(int x,int y){e[++cnt]=(node){y,fi[x]};fi[x]=cnt;return;
}
int p[N],col[N];int pre[N],up[N][20],pl[N][20],dep[N],suf[N];
void dfs(int x,int f){dep[x]=dep[f]+1;pl[x][0]=f;for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];up[x][0]=pre[suf[col[x]]];for(int k=1;up[x][k-1];k++) up[x][k]=up[up[x][k-1]][k-1];int ori=pre[col[x]];pre[col[x]]=x;for(int i=fi[x];~i;i=e[i].nxt){int to=e[i].to;if(to==f) continue;dfs(to,x);}pre[col[x]]=ori;return;
}
inline int Lca(int x,int y){if(dep[x]<dep[y]) swap(x,y);for(int k=17;k>=0;k--){if(dep[pl[x][k]]<dep[y]) continue;x=pl[x][k];}if(x==y) return x;for(int k=17;k>=0;k--){if(pl[x][k]==pl[y][k]) continue;x=pl[x][k];y=pl[y][k];}return pl[x][0];
}
struct query{int s,t,lca,id;
};
vector<query>v[N];
inline int jump(int x,int top){//return color;for(int k=17;k>=0;k--){if(dep[up[x][k]]<dep[top]) continue;x=up[x][k];}return suf[col[x]];
}
struct add{int id,c;
};
vector<add>ad[N];
vector<int>q[N];
void solve1(int x,int f){int ori=pre[col[x]];pre[col[x]]=x;for(query o:v[x]){int s=o.s,t=o.t,lca=o.lca,id=o.id;s=pre[p[1]];if(dep[s]<dep[lca]) ad[lca].push_back((add){id,p[1]});else ad[lca].push_back((add){id,jump(s,lca)});q[t].push_back(id);}for(int i=fi[x];~i;i=e[i].nxt){int to=e[i].to;if(to==f) continue;solve1(to,x);}pre[col[x]]=ori;return;
}
int mx[N],fa[N],siz[N];
struct ope{int op;//1:fa 2:siz 3:mx 4:belint id,ori;
}zhan[N<<3];
int top,nam[N],bel[N],tot;
int find(int x){return fa[x]==x?x:find(fa[x]);
}
inline int New(int val){++tot;fa[tot]=tot;siz[tot]=1;mx[tot]=val;return tot;
}
void merge(int x,int y){x=find(x);y=find(y);if(siz[x]>siz[y]) swap(x,y);zhan[++top]=(ope){1,x,fa[x]};fa[x]=y;zhan[++top]=(ope){2,y,siz[y]};siz[y]+=siz[x];zhan[++top]=(ope){3,y,mx[y]};mx[y]=max(mx[y],mx[x]);return;
}
void del(int tim){while(top!=tim){if(zhan[top].op==1) fa[zhan[top].id]=zhan[top].ori;else if(zhan[top].op==2) siz[zhan[top].id]=zhan[top].ori;else if(zhan[top].op==3) mx[zhan[top].id]=zhan[top].ori;else if(zhan[top].op==4) bel[zhan[top].id]=zhan[top].ori;top--;}return;
}
int ans[N];
int rk[N];
void solve2(int x,int f){int ori=top;for(add o:ad[x]){int id=o.id,c=o.c,now=New(0);nam[id]=now;merge(now,bel[c]);//ans[id]=rk[c];}//assert(mx[find(bel[suf[col[x]]])]==rk[suf[col[x]]]);//assert(mx[find(bel[col[x]])]==rk[col[x]]);merge(bel[col[x]],bel[suf[col[x]]]);//if(mx[find(bel[col[x]])]!=rk[col[x]]+1){//    debug("%d %d\n",mx[find(bel[col[x]])],rk[col[x]]);exit(0);//}//assert(mx[find(bel[col[x]])]==rk[col[x]]+1);zhan[++top]=(ope){4,col[x],bel[col[x]]};bel[col[x]]=New(rk[col[x]]);for(int id:q[x]){int o=nam[id];ans[id]=mx[find(o)];}for(int i=fi[x];~i;i=e[i].nxt){int to=e[i].to;if(to==f) continue;solve2(to,x);}del(ori);
}
int main() {#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();Mx=read();C=read();for(int i=1;i<=C;i++) p[i]=read();for(int i=1;i<=C;i++) suf[p[i]]=p[i+1],rk[p[i]]=i;rk[0]=C+1;for(int i=0;i<=Mx;i++) bel[i]=New(rk[i]);for(int i=1;i<=n;i++) col[i]=read();for(int i=1;i<n;i++){int x=read(),y=read();addline(x,y);addline(y,x);}dfs(1,0);m=read();for(int i=1;i<=m;i++){int s=read(),t=read(),lca=Lca(s,t);v[s].push_back((query){s,t,lca,i});}solve1(1,0);solve2(1,0);for(int i=1;i<=m;i++) printf("%d\n",ans[i]-1);return 0;
}
/*
1
3 3
1000000 2000000
0 0
*/

洛谷P7518:宝石(倍增、可撤销并查集)相关推荐

  1. 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]

    洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...

  2. 洛谷P4768 [NOI2018]归程 [可持久化并查集,Dijkstra]

    题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...

  3. 洛谷 - P2754 [CTSC1999]家园(最大流+并查集)

    题目链接:点击查看 题目大意:现在有k个人类需要从地球上转移到月球上去,现在有n个宇宙中转站,以及m个飞船周期性运载,每个飞船的载客都有一定的上限,但中转站的载客没有上限,现在给出每个飞船的路线,问最 ...

  4. 【洛谷P4997】不围棋【并查集】【模拟】

    题目大意: 题目链接:https://www.luogu.org/problemnew/show/P4997 「不围棋」是一种非常有趣的棋类游戏. 大家都知道,围棋的「气」是指一个棋子所在的联通块相邻 ...

  5. 洛谷 P2343 宝石管理系统

    洛谷 P2343 宝石管理系统 Description GY君购买了一批宝石放进了仓库.有一天GY君心血来潮,想要清点他的宝石,于是把m个宝石都取出来放进了宝石管理系统.每个宝石i都有一个珍贵值vi, ...

  6. 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)

    题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...

  7. 线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解

    题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2) 首先我们考虑这种动态加边删边 ...

  8. CF603E-Pastoral Oddities【CDQ分治,可撤销并查集】

    正题 题目链接:https://www.luogu.com.cn/problem/CF603E 题目大意 开始时有nnn个点,没有边. 依次加入mmm条带权的边,每次加入后询问是否存在一个边集,满足每 ...

  9. BZOJ4358: permu(带撤销并查集 不删除莫队)

    题意 题目链接 Sol 感觉自己已经老的爬不动了.. 想了一会儿,大概用个不删除莫队+带撤销并查集就能搞了吧,\(n \sqrt{n} logn\)应该卡的过去 不过不删除莫队咋写来着?....跑去学 ...

最新文章

  1. Leptonica在VS2010中的编译及简单使用举例
  2. 你应该知道的青否小程序第三方平台
  3. xpath定位中starts-with、contains和text()的用法
  4. 单源最短路径(Dijkstra算法)
  5. iOS开发-缓存图片到沙盒--思路
  6. hdu 1297 递推难题
  7. android 触摸屏(TP)问题现象分析和解决方法
  8. uniapp 即时通讯_uniapp与webview的实时通讯
  9. c语言变量名由啥组成,一个c语言是由什么构成
  10. 求一个数的最大公约数
  11. js 前端导出报错 格式不正确_js-xlsx 实现前端 Excel 导出(支持多 sheet)
  12. python生成泊松分布随机数_python-介绍泊松分布(poisson分布)
  13. 超星学习通小助手多线程工具Python
  14. win10最简单的C盘清理,亲测有效
  15. 如何打开CMD以及简单Dos命令
  16. Apache运行正常,但是localhost却打不开页面
  17. 迪士尼2016年压轴巨作---《海洋奇缘》观后感
  18. kademlia算法学习(区块链P2P网络设计)
  19. python贴吧发帖脚本-python+脚本
  20. 怎么才能快速修改视频格式为TS呢?

热门文章

  1. 从一个骗局谈生活中的基础算法
  2. 锁屏快捷键_全面屏 iPhone 锁屏快捷键美化,让你的 iPhone 更特别
  3. mysql数据压缩存储_压缩文本,然后存储在mysql数据库中
  4. 服务器运行慢都有哪些问题,服务器数据库的运行速度很慢问题
  5. python3抓取图片_通过Python3 爬虫抓取漫画图片
  6. php调用另一个php文件里的变量的值,thinkphp中一个方法调用另一个步骤的变量
  7. java控制系统音量_Java 控制 Windows 系统音量-Go语言中文社区
  8. 文件共享服务器第二部,第二章-构建Samba文件共享服务器.docx
  9. python小游戏——21点
  10. java 声明变量构成_Java—变量