一个知识点不在一道题里说是没有灵魂的

线段树是用来处理区间信息的咯

但是往往因为需要4倍空间让许多人退却,而动态开点的线段树就非常

仿佛只用2倍就可以咯

指针保存位置,即节点信息,是很舒适的,所以用指针动态开点就更

<永无乡题面>

这个题哈,我刚开始学线段树合并时惯例懵,

而且我发现……网上的题解有简短甚至偷懒的,于是我很废了,去问神犇

下面就是,比较清楚的题解

首先我们会发现这个题像一个,图论?

但是并不是,因为他问的并不是图的问题(像最短路?),而是联通性,和排名下标,就不用建图

So,分开考虑

1.联通性:dfs的是想岔了,冰茶几(并查集)适合维护这个----->  O(logN)

2.排名下标:

平衡树,不会合并(哭笑不得)

线段树,不错,如果用权值线段树就可以查排名咯

权值线段树,类似于桶排序,用下标存数,每个节点存的是从L到R的数个数

这样一个数的排名就是左面的节点中个数加一

自带二分,非常快

然后就是合并的操作(这个去专门学也好),用不空的节点直接代替空的节点,把不空的公共节点值相加


另外再说一句,我用指针的new函数了,所以慢死,我从大佬们处得知指针要与结构体数组一块用,达到既美观直观又快的效果

结果:

#include<iostream>
#include<cstring>
#include<cstdio>
#define N 100010
using namespace std;
struct XDS{
XDS *lid,*rid;
int dat,l,r;
XDS(){
lid=rid=NULL;
dat=l=r=0;
}
};XDS *root[N];
int itd[N];
void Build(XDS *&rt,int l,int r){
rt=new XDS();
rt->l=l;
rt->r=r;
}
void add(XDS *&rt,int l,int r,int v){//puts("1");
rt->l=l;
rt->r=r;
if(l==r){
rt->dat++;
return ;
} int mid=(l+r)/2;
if(v<=mid){
if(rt->lid==NULL) rt->lid=new XDS();
add(rt->lid,l,mid,v);
}
else{
if(rt->rid==NULL) rt->rid=new XDS();
add(rt->rid,mid+1,r,v);
}
if(rt->lid!=NULL)
rt->dat+=rt->lid->dat;
if(rt->rid!=NULL)
rt->dat+=rt->rid->dat;
}
inline void Add(XDS *&rt,int v){
add(rt,rt->l,rt->r,v);
}
int kth(XDS *rt,int k){
if(rt->dat<k)return -1;
int n=-1;
if(rt->l==rt->r){
return rt->dat==0?-1:itd[rt->l];
}
if(rt->lid!=NULL&&rt->lid->dat>=k){
n=kth(rt->lid,k);
}
else if(rt->rid!=NULL){
if(rt->lid!=NULL)
n=kth(rt->rid,k-rt->lid->dat);
else{
n=kth(rt->rid,k);
}
}
return n;
}
XDS* mmerge(int l,int r,XDS *a,XDS *b){
if(a==NULL)return b;
if(b==NULL)return a;
XDS *c;Build(c,l,r);
c->dat=a->dat+b->dat;
if(l==r)return c;
int mid=(l+r)/2;
c->lid=mmerge(l,mid,a->lid,b->lid);
c->rid=mmerge(mid+1,r,a->rid,b->rid);
return c;
}
int fa[N];
int faind(int x){
if(x!=fa[x]){
delete root[x];
fa[x]=faind(fa[x]);
}
return fa[x];
}
int isn,bn;
void prerun(){
int a;
for(int i=1;i<=isn;i++){
fa[i]=i;
Build(root[i],0,100000);
scanf("%d",&a);
itd[a]=i;
Add(root[i],a);
}
}
void unity(int x,int y){
x=faind(x);
y=faind(y);
if(x!=y){
fa[x]=y;
root[y]=mmerge(0,100000,root[x],root[y]);
delete root[x];
root[x]=NULL;
}
}
int main(){
int a,b,c;
scanf("%d%d",&isn,&bn);
prerun();
for(int i=1;i<=bn;i++){
scanf("%d%d",&b,&c);
unity(b,c);
}
char ch[3];
scanf("%d",&a);
for(int i=1;i<=a;i++){
scanf("%s%d%d",ch,&b,&c);
if(ch[0]=='Q'){
int q=faind(b);
printf("%d\n",kth(root[q],c));
}
else{
unity(b,c);
}
}
return 0;
}

指针-动态开点&合并线段树的更多相关文章

  1. BZOJ 4636 (动态开节点)线段树

    思路: 偷懒 懒得离散化 搞了个动态开节点的线段树 (其实是一样的--..) 注意会有a=b的情况 要判掉 //By SiriusRen #include <cstdio> #includ ...

  2. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  3. Subtree Minimum Query CodeForces - 893F (线段树合并+线段树动态开点)

    题目链接:https://cn.vjudge.net/problem/CodeForces-893F 题目大意:给你n个点,每一个点有权值,然后这n个点会构成一棵树,边权为1.然后有q次询问,每一次询 ...

  4. HDU 5649 DZY Loves Sorting(二分答案+线段树/线段树合并+线段树分割)

    题意 一个 \(1\) 到 \(n\) 的全排列,\(m\) 种操作,每次将一段区间 \([l,r]\) 按升序或降序排列,求 \(m\) 次操作后的第 \(k\) 位. \(1 \leq n \le ...

  5. bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...

  6. 牛客多校第八场E Explorer(左开右闭线段树+可撤回并查集)题解

    题意: 传送门 有\(n\)个点构成一个无向图,每条边有\(L_i,R_i\)表示这条边只能允许编号为\(L_i\dots R_i\)的人通过,现在问你最多有几个人能从\(1\)走到\(n\). 思路 ...

  7. 【BZOJ-1568】Blue Mary开公司 李超线段树 (标记永久化)

    1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 192[Submit ...

  8. zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

    Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/show ...

  9. BZOJ4552 HEOI2016/TJOI2016排序(线段树合并+线段树分裂)

    很久以前写过二分答案离线的做法,比较好理解.事实上这还是一个线段树合并+分裂的板子题,相比离线做法以更优的复杂度做了更多的事情.具体不说了.怎么交了一遍luogu上就跑第一了啊 #include< ...

随机推荐

  1. 148D

    概率dp+记忆化搜索 dp[i][j][0]表示当前公主走公主赢的概率,dp[i][j][1]表示当前龙走公主赢的概率,然后剩下的就是一些细节的讨论,记忆化搜索很方便 #include<bits ...

  2. 2.27 MapReduce Shuffle过程如何在Job中进行设置

    一.shuffle过程 总的来说: *分区 partitioner *排序 sort *copy (用户无法干涉) 拷贝 *分组 group 可设置 *压缩 compress *combiner ma ...

  3. ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门

    默认的身份认证好授权系统 UserManager用来操作用户的类, Singi用来身份认证的 添加AccountController 先声明SignInManager和UserManager这两个服务 ...

  4. javascript的回调函数

    函数也是对象 想弄明白回调函数,首先的清楚地明白函数的规则.在javascript中,函数是比较奇怪的,但它确确实实是对象.确切地说,函数是用Function()构造函数创建的Function对象.F ...

  5. 51nod 1428【贪心】

    思路: 就是先排序,然后对每个取最小的结束时间. #include <bits/stdc++.h> using namespace std; typedef long long LL; c ...

  6. BestCoder Round #74 (div.1) 1002Shortest Path(hdoj5636)

    哈哈哈哈,我就知道这道题目再扔给我,我还是不会,就是这么菜,哈哈哈 一开始官方题解就没搞懂-然后就看了一下别人的代码,水水过就算了.今天拿到-GG: 题意: 一开始,有一张原图,有一条长度为n的链. ...

  7. python __builtins__ copyright类 (14)

    14.'copyright', 版权 class _Printer(builtins.object) | interactive prompt objects for printing the lic ...

  8. tcpdump笔记

    最好的学习: man tcpdump ....... 一.TCPdump抓包命令  tcpdump是一个用于截取网络分组,并输出分组内容的工具.tcpdump凭借强大的功能和灵活的截取策略,使其成为类 ...

  9. 怎么让普通用户达到root用户也可以拥有权限修改文件(CentOS系统)

    为什么会提出这个问题呢? 答:因为啊,比如我们在大数据集群搭建的时候,经常会需要配置环境变量,如/etc/profile.那么,问题来了,每次必须得都切换到root用户才能,但是呢,如何可以在普通用户 ...

  10. [WOJ1138]最大子序和

    题目链接: WOJ1138 题目分析: 是很经典的一道题,乱搞的方法应该有不少,这里介绍O(n)的单调队列做法 首先维护一个前缀和,然后枚举每一个位置,维护一个前缀和单增的单调队列,但队列仅储存下标, ...