BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123
题意:
思路:总的来说,查询区间第K小利用函数式线段树的减法操作。对于两棵树的合并,将节点少的树暴力插入到节点大的树上面。对于本题,首先,将输入的权值离散化,为已经给出的边建立函数式线段树。对于合并x,y,将y的父节点设为x,然后重新建立y为根的子树的函数式线段树。对于查询x,y,k,设其LCA为p,p的父节点为q,则x+y-p-q就是整个区间。
struct node { int L,R,s; }; node tree[N*400]; int root[N],tot; int f[N][20],w[N],n,m,K,d[N],size[N]; vector<int> g[N]; int M; int b[N]; int build(int a,int b) { int k=++tot; tree[k].s=0; if(a==b) return k; int mid=(a+b)>>1; tree[k].L=build(a,mid); tree[k].R=build(mid+1,b); return k; } int insert(int c,int s,int a,int b) { int k=++tot; tree[k]=tree[c]; tree[k].s++; if(a==b) return k; int mid=(a+b)>>1; if(s<=mid) tree[k].L=insert(tree[c].L,s,a,mid); else tree[k].R=insert(tree[c].R,s,mid+1,b); return k; } int visit[N],X; void BFS(int u) { queue<int> Q; Q.push(u); int i,v; while(!Q.empty()) { u=Q.front(); Q.pop(); visit[u]=X; root[u]=insert(root[f[u][0]],w[u],0,M); for(i=1;i<20;i++) f[u][i]=f[f[u][i-1]][i-1]; FOR0(i,SZ(g[u])) { v=g[u][i]; if(visit[v]==X) continue; f[v][0]=u; d[v]=d[u]+1; Q.push(v); } } } int get(int x,int k) { int i; FOR0(i,20) if(k&(1<<i)) x=f[x][i]; return x; } int getLca(int x,int y) { if(d[x]>d[y]) swap(x,y); y=get(y,d[y]-d[x]); if(x==y) return x; int i; for(i=19;i>=0;i--) if(f[x][i]&&f[y][i]&&f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } return f[x][0]; } #define L(a) tree[tree[a].L].s int query(int a,int b,int c,int d,int k,int L,int R) { if(L==R) return L; int s=L(a)+L(b)-L(c)-L(d); int mid=(L+R)>>1; if(k<=s) return query(tree[a].L,tree[b].L,tree[c].L,tree[d].L,k,L,mid); return query(tree[a].R,tree[b].R,tree[c].R,tree[d].R,k-s,mid+1,R); } void go() { int x,y,k,p,last=0; char op[10]; int fx,fy; while(K--) { RD(op); if(op[0]=='Q') { RD(x,y,k); x^=last; y^=last; k^=last; p=getLca(x,y); last=b[query(root[x],root[y],root[p],root[f[p][0]],k,0,M)]; PR(last); } else { RD(x,y); x^=last; y^=last; fx=get(x,d[x]); fy=get(y,d[y]); g[x].pb(y); g[y].pb(x); X++; if(size[fx]>=size[fy]) { size[fx]+=size[fy]; f[y][0]=x; d[y]=d[x]+1; visit[x]=X; BFS(y); } else { size[fy]+=size[fx]; f[x][0]=y; d[x]=d[y]+1; visit[y]=X; BFS(x); } } } } int main() { int CC; RD(CC); RD(n,m,K); int i,j,u,v; FOR1(i,n) RD(w[i]),size[i]=1,b[i]=w[i]; sort(b+1,b+n+1); M=unique(b+1,b+n+1)-(b+1); FOR1(i,n) w[i]=lower_bound(b+1,b+M+1,w[i])-b; tot=0; root[0]=build(0,M); FOR1(i,m) { RD(u,v); g[u].pb(v); g[v].pb(u); } FOR1(i,n) f[i][0]=-1; FOR1(i,n) if(f[i][0]==-1) { f[i][0]=0; d[i]=0; X++; BFS(i); } go(); }
BZOJ 3123 森林(函数式线段树)的更多相关文章
- bzoj 3123 可持久化线段树启发式合并
首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...
- BZOJ 3207 花神的嘲讽计划Ⅰ(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3207 题意:给出一个数列,若干询问.每个询问查询[L,R]区间内是否存在某个长度为K的子 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- POJ2104 K-th number 函数式线段树
很久没打代码了,不知道为什么,昨天考岭南文化之前突然开始思考起这个问题来,这个问题据说有很多种方法,划分树什么的,不过对于我现在这种水平还是用熟悉的线段树做比较好.这到题今年8月份的时候曾经做过,那个 ...
- [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)
这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...
- hdu 5111 树链剖分加函数式线段树
这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...
- Codeforces538F A Heap of Heaps(函数式线段树)
题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 一个直觉的思想就是暴力, ...
- Bzoj 2752 高速公路 (期望,线段树)
Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...
- BZOJ - 3123 森林 (可持久化线段树+启发式合并)
题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...
随机推荐
- hadoop相关问题
发现一篇不错的文章,转一下.http://www.cnblogs.com/xuekyo/p/3386610.html HDFS导论(转) 1.流式数据访问 HDFS的构建思想是这样的:一次写入,多 ...
- PHP Cookie处理函数
(o゜▽゜)o☆[BINGO!] ok,我们先看看cookie是什么东东? cookie是服务器留在客户端的用于识别用户或者存储一些数据的小文件(注意,session存储在服务器端,这是两者的区别之一 ...
- 模仿开发H5游戏,看你有多色
开发记录 前言 之前跟着慕课网学习开发H5小游戏开心鱼,勾起我的兴趣. 在写代码的过程中,不怎么会遇到问题.虽然代码是亲手敲出来的,但是由于并没有对游戏的整体思路,所以并不知道开发与优化的过程. 为了 ...
- Madwifi Mad coding:自底向上分析associated_sta的更新过程 —— RSSI和MACADDR等信息获取的底层原理
Madwifi驱动工作在AP模式下时,可以在/proc/net/madwifi/ath0/associated_sta文件中得到所有接入的用户的MAC地址.实时平均RSSI,和last_rx三个信息. ...
- 【BZOJ】【2819】NIM
这题……咋说捏,其实是一道披着博弈论外衣的树上操作问题…… 随便用dfs序或者树链剖分转成序列,然后查询路径上的所有点的NIM和(异或和)就行了,毕竟除了是在树上以外,就是裸的NIM问题. 树链剖分: ...
- 2014 Multi-University Training Contest 10
官方解题报告:http://blog.sina.com.cn/s/blog_6bddecdc0102v01l.html A simple brute force problem. http://acm ...
- setblendstate & setdepthstencilstate
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476462(v=vs.85).aspx blendstate blendfacto ...
- 循环队列实现(C++) Ring Buffer
循环队列:队列有着先入先出的特性.但是对于队列如果删除队头以后剩下的空间将不会被释放,又由于队列只能由队尾插入这就导致被删除部分的空间被浪费.解决这个问题就是循环队列.循环队列顾名思义就是将队列串起来 ...
- Web Server 和 HTTP 协议
https://toutiao.io/posts/xm2fr/preview 一直在找实习,有点什么东西直接就在evernote里面记了,也没时间来更新到这里.找实习真是个蛋疼的事,一直找的是困难模式 ...
- 【QT】OpenCV配置
很郁闷的表示我的opencv放在 D:\\program files 里面路径有个空格,导致我不得不把整个opencv又拷贝到了一个没有空格的路径下面命名为opencvForQt 网上有各种用CMa ...