P3302-[SDOI2013]森林【主席树,LCA,启发式合并】

正题

题目链接:https://www.luogu.com.cn/problem/P3302


题目大意

nnn个点的一个森林,要求支持以下操作

  1. 连接两个不连通的点
  2. 询问两个点之间最短路径上第kkk大的数

解题思路

需要支持查询第kkk大,是必定使用主席树的,所以考虑如何合并两棵树可以更快。

考虑启发式合并,每次将小的点合并到大的点上面,那样每个点最多被合并log⁡n\log nlogn次。也就是每次合并我们就将小的那颗树完全重构

考虑如何查询,我们可以用主席树上储存根节点到该点的每个数的个数,然后查询时我们可以用两个点到根节点的答案减去他们的lcalcalca处和lcalcalca的父节点处的答案即可。


codecodecode

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=8e4+10,M=N*600,K=17;
struct node{ll to,next;
}a[N*2];
ll n,m,t,cnt,tot;
ll w[N],b[N],ls[N],rt[N];
ll root[N],siz[N],dep[N],f[N][K];
struct Seq_Tree{ll ls[M],rs[M],w[M],cnt;void Build(ll &x,ll l,ll r){if(!x)x=++cnt;w[x]=0;if(l==r)return;ll mid=(l+r)>>1;Build(ls[x],l,mid);Build(rs[x],mid+1,r);return;}ll Change(ll y,ll l,ll r,ll pos){ll x=++cnt,mid=(l+r)>>1;w[x]=w[y]+1;ls[x]=ls[y];rs[x]=rs[y];if(l==r)return x;if(pos<=mid)ls[x]=Change(ls[y],l,mid,pos);else rs[x]=Change(rs[y],mid+1,r,pos);return x;}ll Ask(ll x,ll y,ll lca,ll fa,ll l,ll r,ll k){if(l==r)return b[l];ll mid=(l+r)>>1,val=w[ls[x]]+w[ls[y]]-w[ls[lca]]-w[ls[fa]];if(val>=k)return Ask(ls[x],ls[y],ls[lca],ls[fa],l,mid,k);return Ask(rs[x],rs[y],rs[lca],rs[fa],mid+1,r,k-val);}
}T;
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;return;
}
void dfs(ll x,ll fa){siz[root[x]]++;f[x][0]=fa;dep[x]=dep[fa]+1;for(ll i=1;i<K;i++)f[x][i]=f[f[x][i-1]][i-1];rt[x]=T.Change(rt[fa],1,cnt,w[x]);for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==fa)continue;root[y]=root[x];dfs(y,x);}return;
}
void Connect(ll x,ll y){if(siz[root[x]]<siz[root[y]])swap(x,y);root[y]=root[x];dfs(y,x);addl(x,y);return;
}
ll LCA(ll x,ll y){if(dep[x]>dep[y])swap(x,y);for(ll i=K-1;i>=0;i--)if(dep[f[y][i]]>=dep[x])y=f[y][i];if(x==y)return x;for(ll i=K-1;i>=0;i--)if(f[y][i]!=f[x][i])x=f[x][i],y=f[y][i];return f[x][0];
}
int main()
{ll testcase;scanf("%lld",&testcase);scanf("%lld%lld%lld",&n,&m,&t);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]),b[++cnt]=w[i];sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;for(ll i=1;i<=n;i++)w[i]=lower_bound(b+1,b+1+cnt,w[i])-b;for(ll i=1;i<=m;i++){ll x,y;scanf("%lld%lld",&x,&y);addl(x,y);}T.Build(rt[0],1,cnt);for(ll i=1;i<=n;i++)if(!root[i]){root[i]=i;dfs(i,0);}ll last=0;for(ll i=1;i<=t;i++){char op[4];ll x,y,k;scanf("%s",op);if(op[0]=='Q'){scanf("%lld%lld%lld",&x,&y,&k);x^=last;y^=last;k^=last;ll lca=LCA(x,y);last=T.Ask(rt[x],rt[y],rt[lca],rt[f[lca][0]],1,cnt,k);printf("%lld\n",last);}else{scanf("%lld%lld",&x,&y);x^=last;y^=last;Connect(x,y);}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321209.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

codeforces gym-101741 Cover the Paths LCA、离线询问

题目 题目链接 题意 给出一棵树。 给出一堆路径&#xff0c;找出最少一个最少的点的集合&#xff0c;使得所有的路径都经过集合中的至少一个点。 题解 考虑一个路径的两个端点&#xff0c;从下往上最后一个能被经过的点就是这两点的LCA。 因此我们做整棵树dfs&#xff0…

【结论】单元格(jzoj 1509)

单元格 题目大意&#xff1a; 在一个RC的矩形中选三个点&#xff0c;使他们行列各不同&#xff0c;定义“费用”为&#xff0c;这三个点之间的行列的差值的和&#xff08;1,2和3,4费用是差值是&#xff08;3-1&#xff09;&#xff08;4-2&#xff09;224&#xff09;&#x…

nssl1487-图

正题 题目大意 nnn个点nnn条边的图&#xff0c;每条边的边权为两个连接节点的权值和&#xff0c;给出所有边权&#xff0c;求每个节点权值&#xff08;保证唯一的环为奇环&#xff09; 解题思路 首先并查集找到环上相邻的两个点&#xff0c;然后可以发现这两个点之间有两个关系…

codeforces gym-101741 Subsequence Sum Queries 分治+离线

题目 这里写链接内容 题意 给出一个最长为200000200000数列 给出一堆最多为200000200000个询问区间&#xff0c;问从这些区间中取出一些数使得数字之和是m的倍数&#xff0c;有多少种方案。其中保证1≤m≤201≤m≤20。 题解 最容易想到的方法就是倍增dp来做。 定义f[i][…

【DP】剪草(jzoj 1510)

剪草 题目大意&#xff1a; 有n棵小草&#xff0c;B某看它们很不顺眼&#xff0c;想让他们的高度总和不大于H&#xff0c;它们一开始各有一个高度&#xff0c;然后它们各有一个固定的生长值&#xff0c;B某每个单位时间可以将一棵草减掉&#xff08;让他的高度变为0&#xff…

nssl1488-上升子序列【贪心,dp】

正题 题目大意 长度为nnn的序列&#xff0c;分割成两个上升子序列要求长度差最小 解题思路 我们对于i<j,ai≥aji<j,a_i\geq a_ji<j,ai​≥aj​的点之间连边&#xff0c;然后可以对于一个联通块进行二分图染色&#xff0c;我们可以发现&#xff0c;如果我们先固定一个…

经典题:poj2104-区间第k小 整体二分学习

写在前面 区间第k小 可以说是一个很经典的数据结构题了&#xff0c;这道题有很多种解法比如莫队离线、主席树、整体二分等等。 之前用莫队和主席树写过这道题&#xff0c;今天来学习一个以前不会的算法——整体二分。 因为最近遇到一个类似于整体二分的题目&#xff0c;就是…

2019.01.28【NOIP普及组】模拟赛C组总结

总结 这次比赛的得分是&#xff1a;100000100&#xff08;rank 5&#xff09; 这次第一题打了一会&#xff0c;又想到会超时就想了另一个不会超时的方法&#xff0c;就A了&#xff0c;第二题用了一种十分智障的方法&#xff0c;但定义了一个int结构的time&#xff0c;哪知不可…

nssl1489-大冰隙2【树链剖分,线段树】

正题 题目大意 nnn只叫龙&#xff0c;mmm个操作。每只叫龙有种类(0/1)(0/1)(0/1)和攻击力。 修改某只叫龙的攻击力取出l∼rl\sim rl∼r只叫龙&#xff0c;然后将连续的种类为010101的叫龙消灭只到没有连续的010101为止&#xff0c;求剩下的叫龙中攻击力最高是多少 解题思路 初…

【对数】YY(jzoj 1438)

YY 题目大意&#xff1a; 给出一个超大正整数S&#xff0c;求出nn{n}^{n}nnS中n的解 样例输入 387420489 样例输出 9 数据范围限制 S的位数小于500000 解题思路&#xff1a; 看到数据&#xff0c;爆搜是不可能的&#xff0c;我们用数字的位数来做&#xff0c;我们用一…

codeforces gym-101741 Elevator 动态规划、单调队列

题目 这里写链接内容 题解 注意&#xff1a;题目给出是按照时间给出的顺序。 我们考虑第ii个人要上的楼高h[i]" role="presentation" style="position: relative;">h[i]h[i]&#xff0c;排在第ii个人前面的,所有要人上的楼高度&#x2264;h[…

P5952-[POI2018]水箱【最小生成树】

正题 题目链接:https://www.luogu.com.cn/problem/P5952 题目大意 n∗mn*mn∗m个格子&#xff0c;最外层有无限高的墙&#xff0c;然后每个格子之间有一睹给定高度的墙&#xff0c;然后求有多少种不同的水位情况。 解题思路 首先我们如果将墙看成边&#xff0c;那么会造成影响…

【枚举】LAGNO(jzoj 1149)

LAGNO 题目大意&#xff1a; 给你一个88的矩阵&#xff0c;里面有黑棋&#xff08;B&#xff09;&#xff0c;白棋&#xff08;W&#xff09;&#xff0c;还有一些格子没棋子&#xff08;.&#xff09;&#xff0c;当两个黑棋在同一条直线上&#xff0c;并且他们之间全是白棋…

HDU5833 异或方程组的初步学习

题目 题目链接 题解 选出来的数相乘要能组成一个完全平方数&#xff0c;则这个完全平方数进行素数分解以后&#xff0c;相同的素因子的个数是偶数个。 基于这个结论&#xff0c;我们对与每一个候选数a[i]a[i]进行质因数分解&#xff08;最多有303个不同的质因子&#xff09…

codeforces 962E Byteland, Berland and Disputed Cities 最小生成树变形

题目 题目链接 题意 在OxOx轴上有一堆点&#xff0c;这些点有三种类型R、B、PR、B、P型&#xff0c;现在要求添加一些线段把这些点连起来&#xff0c;使得如果去掉RR类型点,剩下的点都是联通的。如果去掉B" role="presentation" style="position: rela…

P6772-[NOI2020]美食家【矩阵乘法,倍增】

前言 我考场&#xff08;线上赛&#xff09;切NOI的题了&#xff01; 正题 题目链接:https://www.luogu.com.cn/problem/P6772 题目大意 nnn个点mmm条边&#xff0c;每个城市有不同的愉悦值&#xff0c;从111出发&#xff0c;要求经过TTT的时间后回到点111(不能原地停留。 …

【DP】【记忆化搜索】NIKOLA(jzoj 1150)

NIKOLA 题目大意&#xff1a; NIKOLA画了一排数字&#xff0c;他一开始在1&#xff0c;他可以往前跳T1格&#xff08;T为上一次跳到此格跳的格数&#xff09;&#xff0c;或往后T格&#xff08;T一开始为0&#xff09;&#xff0c;但不能跳出界&#xff0c;没跳到一个格子&am…

codeforces gym-101673 Twenty Four, Again 24点,枚举表达式树过题

题目 题目链接 题意 给出4个数字&#xff0c;让你任意指定运算符&#xff08;3个&#xff09;、增加括号、交换数&#xff0c;问组成24点的代价最小是多少。 增加括号&#xff1a;代价为1。 交换数的顺序&#xff1a;代价为2。 题解 方法就是暴力枚举&#xff0c;我们可…

【模拟】pjesma(jzoj 1151)

pjesma 题目大意&#xff1a; 一首歌放出m个单词&#xff0c;M某知道n个关键词&#xff0c;当关键词放出一半以上时&#xff0c;M某就知道这是哪首歌&#xff0c;问在放出第几个单词时&#xff0c;M某知道这首歌是哪首歌 样例输入 3 sedam gladnih patuljaka 7 sedam dana …

在ASP.NET Core中使用brotli压缩

Brotli是一种全新的数据格式&#xff0c;可以提供比Zopfli高20-26%的压缩比。据谷歌研究&#xff0c;Brotli压缩速度同zlib的Deflate实现大致相同&#xff0c;而在Canterbury语料库上的压缩密度比LZMA和bzip2略大。 链接&#xff1a;Google开源Brotli压缩算法 微软使用了一种基…