首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca(x,y)]-rot[lca(x,y)->father]这棵树来得知这个链的信息。

  那么对于连边操作,相当于合并两棵树,我们可以将树的节点数小的树全部拆掉连到节点大的树中,这样每个点最多会被操作logn次,每次操作的时间复杂度为logn,所以是mlog^2n的。

  反思:对于树的连通性我是用并查集维护的,对于合并操作还需要dfs一次小的树来维护各种信息,但是忘记对x,y点连边了,导致一直RE.(RE是因为某次值不正确,导致下一次^的点超过n)。

     各种慢= =。

/**************************************************************Problem: 3123User: BLADEVILLanguage: C++Result: AcceptedTime:16612 msMemory:81512 kb
****************************************************************///By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
#define maxm 200010using namespace std;struct rec {int key,num;rec() {key=num=0;}
}a[maxn];struct segment {int left,right,cnt;int son[2];segment() {left=right=cnt=0;memset(son,0,sizeof son);}
}t[maxn<<5];int n,m,l,N,tot;
int pre[maxm<<1],last[maxm<<1],other[maxm<<1];
int ans[maxn],rot[maxn];
int dep[maxn],jump[maxn][20],father[maxn],size[maxn],que[maxn];void connect(int x,int y) {pre[++l]=last[x];last[x]=l;other[l]=y;
}int getfather(int x) {if (father[x]==x) return x;return father[x]=getfather(father[x]);
}void dfs(int x,int fa) {jump[x][0]=fa; dep[x]=dep[fa]+1;for (int p=last[x];p;p=pre[p]) {if (other[p]==fa) continue;dfs(other[p],x);}
}bool cmp1(rec x,rec y) {return x.key<y.key;
}bool cmp2(rec x,rec y) {return x.num<y.num;
}int lca(int x,int y) {if (dep[x]>dep[y]) swap(x,y);int d=dep[y]-dep[x];for (int i=0;i<=16;i++) if (d&(1<<i)) y=jump[y][i];if (x==y) return x;for (int i=16;i>=0;i--) if (jump[x][i]!=jump[y][i]) x=jump[x][i],y=jump[y][i];return jump[x][0];
}void build(int &x,int l,int r) {if (!x) x=++tot;t[x].left=l; t[x].right=r;if (t[x].left==t[x].right) return ;int mid=t[x].left+t[x].right>>1;build(t[x].son[0],l,mid); build(t[x].son[1],mid+1,r);
}void insert(int &x,int rot,int key) {if (!x) x=++tot;t[x].left=t[rot].left; t[x].right=t[rot].right;if (t[x].left==t[x].right) {t[x].cnt=t[rot].cnt+1;return ;}int mid=t[x].left+t[x].right>>1;if (key>mid) {t[x].son[0]=t[rot].son[0];insert(t[x].son[1],t[rot].son[1],key);} else {t[x].son[1]=t[rot].son[1];insert(t[x].son[0],t[rot].son[0],key);}t[x].cnt=t[rot].cnt+1;
}int query(int x,int y,int l1,int l2,int k) {//printf("%d %d %d ",x,t[x].left,t[x].right);if (t[x].left==t[x].right) return t[x].left;int cur=t[t[x].son[0]].cnt+t[t[y].son[0]].cnt-t[t[l1].son[0]].cnt-t[t[l2].son[0]].cnt;//printf("%d\n",cur);if (k>cur) return query(t[x].son[1],t[y].son[1],t[l1].son[1],t[l2].son[1],k-cur); elsereturn query(t[x].son[0],t[y].son[0],t[l1].son[0],t[l2].son[0],k);
}void make(int x,int fa) {insert(rot[x],rot[fa],a[x].key);for (int p=last[x];p;p=pre[p]) {if (other[p]==fa) continue;make(other[p],x);}
}void update(int x,int fa,int j) {jump[x][j]=jump[jump[x][j-1]][j-1];for (int p=last[x];p;p=pre[p]) {if (other[p]==fa) continue;update(other[p],x,j);}
}void merge(int x,int y) {int fx=getfather(x),fy=getfather(y);//if (x==1) printf("%d %d\n",fx,fy);if (size[fx]<size[fy]) swap(x,y);fx=getfather(x),fy=getfather(y);father[fy]=fx; size[fx]+=size[fy];dfs(y,x); make(y,x); for (int i=1;i<=16;i++) update(y,x,i);//for (int i=1;i<=n;i++) printf("%d %d\n",i,jump[i][0]);
}int main() {//freopen("3123.in","r",stdin); freopen("3123.out","w",stdout);int task; scanf("%d",&task);scanf("%d%d%d",&n,&m,&task);for (int i=1;i<=n;i++) scanf("%d",&a[a[i].num=i].key); sort(a+1,a+1+n,cmp1);int cur; ans[1]=cur=a[1].key;for (int i=1,j=1;i<=n;i++) if (a[i].key==cur) a[i].key=j; else ans[++j]=cur=a[i].key,a[i].key=j,N=j;sort(a+1,a+1+n,cmp2);//for (int i=1;i<=n;i++) printf("%d ",ans[i]); printf("\n");//for (int i=1;i<=n;i++) printf("%d ",a[i].key); printf("\n");for (int i=1;i<=n;i++) father[i]=i,size[i]=1;for (int i=1;i<=m;i++) {int x,y; scanf("%d%d",&x,&y);connect(x,y); connect(y,x);int fx=getfather(x),fy=getfather(y);father[fx]=fy; size[fy]+=size[fx];}for (int i=1;i<=n;i++) if (!jump[i][0]) dfs(i,0);//for (int i=1;i<=n;i++) printf("%d %d\n",i,father[i]);//for (int i=1;i<=n;i++) if (i==getfather(i)) printf("%d %d\n",i,size[i]);for (int j=1;j<=16;j++)for (int i=1;i<=n;i++) jump[i][j]=jump[jump[i][j-1]][j-1];build(rot[0],1,N);for (int i=1;i<=n;i++) if (!jump[i][0]) make(i,0);int ANS=0; char Q[3];while (task--) {scanf("%s",Q);if (Q[0]=='Q') {int x,y,k; scanf("%d%d%d",&x,&y,&k);x^=ANS; y^=ANS; k^=ANS;//printf("|%d %d %d\n",x,y,k);int rr=lca(x,y); //printf("%d\n",rr);//for (int i=1;i<=n;i++) printf("%d %d\n",i,jump[i][0]);printf("%d\n",ANS=ans[query(rot[x],rot[y],rot[rr],rot[jump[rr][0]],k)]);//for (int i=1;i<=n;i++) if (i==getfather(i)) printf("%d %d\n",i,size[i]);} else {    int x,y; scanf("%d%d",&x,&y);x^=ANS; y^=ANS; connect(x,y); connect(y,x);//printf("|%d %d\n",x,y);
            merge(x,y);}}return 0;
}

 

转载于:https://www.cnblogs.com/BLADEVIL/p/3678176.html

bzoj 3123 可持久化线段树启发式合并相关推荐

  1. bzoj 36733674 可持久化并查集加强版(可持久化线段树+启发式合并)

    CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...

  2. bzoj 2733: [HNOI2012]永无乡(线段树启发式合并)

    2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3850  Solved: 2061 [Submit][Sta ...

  3. [CSP-S模拟测试]:模板(ac)(线段树启发式合并)

    题目描述 辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了. 他每天都被$katarina$大神虐,仗着自己学过一些姿势就给$katarina$大神出了一道题. 有一棵$n$个节点的以$1$ ...

  4. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  5. 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】

    题意:给一个串 SSS,qqq 次询问,每次给定串 TTT 和 l,rl,rl,r ,求有多少个本质不同的串是 TTT 的子串而不是 Sl-rS_{l\dots r}Sl-r​ 的子串. ∣S∣≤5× ...

  6. 【CF700E】Cool Slogans【后缀自动机】【可持久化线段树合并】【树上倍增】

    传送门 题意:给定字符串SSS,求一堆字符串s1,s2,s3,...,sks_1,s_2,s_3,...,s_ks1​,s2​,s3​,...,sk​,满足s1s_1s1​是SSS的子串,且sis_i ...

  7. [BZOJ 3207] 花神的嘲讽计划Ⅰ【Hash + 可持久化线段树】

    题目链接:BZOJ - 3207 题目分析 先使用Hash,把每个长度为 k 的序列转为一个整数,然后题目就转化为了询问某个区间内有没有整数 x . 这一步可以使用可持久化线段树来做,虽然感觉可以有更 ...

  8. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  9. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  10. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

最新文章

  1. 计算机在我国开始被应用于,(),计算机在我国也开始被应用于会计工作,并由此引出了“会计电算化”这一具有强烈中国特色的专 - 试题答案网问答...
  2. python 等值线 标注 间距、控制_python - Matplotlib-Contourf-如何使刻度线间距不均匀? - 堆栈内存溢出...
  3. mysql不同的类的个数_Mysql数据库-SQL优化-统计某种类型的个数
  4. 《Nature》颠覆性发现!第四种热传递方式找到了
  5. 100人每人100元每次一人分1元给另一人问题matalb 求解
  6. arduino openmv 显示图像_OpenMV与Arduino NUO的连接方式
  7. Socket超时时间设置
  8. JSTL获取session中的值
  9. rsync文件同步应用--客户端的配置
  10. 开源的东西,只是用来参考学习,要商用路途遥远
  11. 图灵程序设计丛书 算法(第4版)pdf
  12. 【计算机网络】零拷贝之MMAP
  13. 计算机修改桌面图标大小,windows更改桌面图标大小设置
  14. 【单例模式、多例模式、枚举、工厂模式】
  15. txt转mobi格式
  16. sqlite3的使用
  17. 半导体上下游供应商汇总(值得收藏)
  18. B、BL、BX、BLX 和 BXJ
  19. 计算机近几年自考本科题,近几年自考管理系统中计算机硬应用题汇总.doc
  20. 搞懂事件循环,面试不再害怕console输出问题。(自整)

热门文章

  1. 【C++】内存4区---代码区、全局区、栈区、堆区
  2. 【github】命令和错误小结
  3. 初步了解Java内部类
  4. VirtuoZo数字摄影测量(二)——模型定向与核线影像生成
  5. mysql php 空格函数_MySQL_mysql 强大的trim() 函数,mysql中的去除左空格函数: LTRI - phpStudy...
  6. 数据结构-03-队列
  7. ip访问次数统计 nginx_nginx访问量统计
  8. Apache Flink 零基础入门(八): SQL 编程实践
  9. 吊炸天!15岁成杀人犯,监狱里学编程,37岁获释后年薪70万
  10. 几个清华、北邮、同济学霸的公号,值得关注