P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]
又是码农题…
利用克鲁斯卡尔重构树的性质
我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优。
于是第二问就可以直接 LCA 求出来了…
至于第三问,dfs序一下,然后求子树…考虑莫队
修改直接带修莫队,没了。
#include <bits/stdc++.h>
using namespace std ;
int min(int x , int y) { return x < y ? x : y ; }
void swap(int & x , int & y) { x ^= y ^= x ^= y ; }
int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c & 15) ; c = getchar() ; }
return x * f ;
}
void print(int x) {
char _st[20] ; int tp = 0 ;
if(! x) { putchar('0') ; }
while(x) { _st[++ tp] = (x % 10) ^ 48 ; x /= 10 ; }
while(tp) { putchar(_st[tp --]) ; }
putchar('\n') ;
}
const int N = 1e5 + 10 ;
const int M = 3e5 + 10 ;
const int Q = 2e5 + 10 ;
struct Edge { int u , v , w ; } E[M] ;
struct _Link { int v , nxt ; } e[N << 1] ;
struct Change { int pos , col ; } qc[Q] ;
struct Qry { int l , r , id , t ; } qr[Q] ;
int n , m , q , change_cnt = 0 , qry_cnt = 0 , len = 0 ;
int col[N] , fa[N << 1] , val[N << 1] , head[N << 1] , cnt = 0 , f[N << 1][22] , d[N << 1] ;
int rev[N << 1] , dfn[N << 1] , sz[N << 1] , idx = 0 , ans[Q] , _cnt[N << 1] , bl[N] ;
void Link(int u , int v) { e[++ cnt] = { v , head[u] } ; head[u] = cnt ; }
void dfsfa(int u) {
for(int i = head[u] ; i ; i = e[i].nxt) { d[e[i].v] = d[f[e[i].v][0] = u] + 1 ; dfsfa(e[i].v) ; }
}
void dfssz(int u) {
if(u <= n) { rev[dfn[u] = ++ idx] = u ; sz[u] = 1 ; } else dfn[u] = 1e9 ;
for(int i = head[u] ; i ; i = e[i].nxt) { dfssz(e[i].v) ; sz[u] += sz[e[i].v] ; dfn[u] = min(dfn[u] , dfn[e[i].v]) ; }
}
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]) ; }
void Kruskal() {
int tot = n ; sort(E + 1 , E + m + 1 , [](Edge x , Edge y) { return x.w < y.w ; }) ;
for(int i = 1 ; i <= (n << 1) ; i ++) fa[i] = i ;
for(int i = 1 ; i <= m ; i ++) {
int u = find(E[i].u) , v = find(E[i].v) ;
if(u ^ v) { ++ tot ; val[fa[tot] = fa[u] = fa[v] = tot] = E[i].w ; Link(tot , u) ; Link(tot , v) ; }
} dfsfa(tot) ; dfssz(tot) ;
}
int Lca(int u , int v) {
if(d[u] < d[v]) swap(u , v) ;
for(int i = 20 ; ~ i ; i --) if(d[f[u][i]] >= d[v]) u = f[u][i] ; if(u == v) return u ;
for(int i = 20 ; ~ i ; i --) if(f[u][i] ^ f[v][i]) { u = f[u][i] ; v = f[v][i] ; } return f[u][0] ;
}
int gettop(int u , int _val) { for(int i = 20 ; ~ i ; i --) if(f[u][i] && val[f[u][i]] <= _val) u = f[u][i] ; return u ; }
int Ans = 0 ;
void ins(int x) { if(++ _cnt[x] == 1) ++ Ans ; }
void del(int x) { if(-- _cnt[x] == 0) -- Ans ; }
void modify(int x , int now) {
if(qc[x].pos >= qr[now].l && qc[x].pos <= qr[now].r) { del(col[rev[qc[x].pos]]) ; ins(qc[x].col) ; }
swap(qc[x].col , col[rev[qc[x].pos]]) ;
}
void Solve() {
for(int j = 1 ; j <= 20 ; j ++)
for(int i = 1 ; i <= (n << 1) ; i ++) f[i][j] = f[f[i][j - 1]][j - 1] ;
for(int i = 1 ; i <= q ; i ++) {
int opt = read() ;
if(opt == 1) { int pos = read() , col = read() ; qc[++ change_cnt] = { dfn[pos] , col } ; }
if(opt == 2) { ans[++ qry_cnt] = val[Lca(read() , read())] ; }
if(opt == 3) { ++ qry_cnt ; int x = read() , top = gettop(x , read()) ; qr[++ len] = { dfn[top] , dfn[top] + sz[top] - 1 , qry_cnt , change_cnt} ; }
}
vector < int > b ; for(int i = 1 ; i <= n ; i ++) b.push_back(col[i]) ;
for(int i = 1 ; i <= change_cnt ; i ++) b.push_back(qc[i].col) ;
sort(b.begin() , b.end()) ; b.erase(unique(b.begin() , b.end()) , b.end()) ;
for(int i = 1 ; i <= n ; i ++) col[i] = lower_bound(b.begin() , b.end() , col[i]) - b.begin() ;
for(int i = 1 ; i <= change_cnt ; i ++) qc[i].col = lower_bound(b.begin() , b.end() , qc[i].col) - b.begin() ;
int block = sqrt(n * (2.0 / 3.0)) ; for(int i = 1 ; i <= n ; i ++) bl[i] = (i - 1) / block + 1 ;
sort(qr + 1 , qr + len + 1 , [](Qry x , Qry y) {
if(bl[x.l] ^ bl[y.l]) return x.l < y.l ;
if(bl[x.r] ^ bl[y.r]) return x.r < y.r ;
return x.t < y.t ;
}) ;
int l = 1 , r = 0 , now_t = 0 ;
for(int i = 1 ; i <= len; i ++) {
while(l > qr[i].l) ins(col[rev[-- l]]) ; while(r < qr[i].r) ins(col[rev[++ r]]) ;
while(l < qr[i].l) del(col[rev[l ++]]) ; while(r > qr[i].r) del(col[rev[r --]]) ;
while(now_t < qr[i].t) modify(++ now_t , i) ; while(now_t > qr[i].t) modify(now_t -- , i) ;
ans[qr[i].id] = Ans ;
}
for(int i = 1 ; i <= qry_cnt ; i ++) print(ans[i]) ;
}
signed main() {
n = read() ; m = read() ; q = read() ;
for(int i = 1 ; i <= n ; i ++) { col[i] = read() ; }
for(int i = 1 ; i <= m ; i ++) { int u = read() , v = read() , w = read() ; E[i] = { u , v , w } ; }
Kruskal() ; Solve() ;
return 0 ;
}
P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]的更多相关文章
- 【Luogu P5168】xtq玩魔塔(Kruskal 重构树 & 树状数组 & set)
Description 给定一个 \(n\) 个顶点,\(m\) 条边的无向联通图,点.边带权. 先有 \(q\) 次修改或询问,每个指令形如 \(\text{opt}\ x\ y\): \(\tex ...
- Luogu P5168 xtq玩魔塔
这题不错啊,结合了一些不太传统的姿势. 首先看到题目有一问从一个点到另一个点边权最小值.想到了什么? 克鲁斯卡尔生成树+倍增?好吧其实有一个更常用NB的算法叫克鲁斯卡尔重构树 (不会的可以看dalao ...
- [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树
这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树.它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks. 在Bytemountains有N座山峰,每座山峰 ...
- 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)
传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...
- 【BZOJ4242】水壶(克鲁斯卡尔重构树,BFS)
[BZOJ4242]水壶(克鲁斯卡尔重构树,BFS) 题面 BZOJ然而是权限题. Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长 ...
- 洛谷 P1967 货车运输(克鲁斯卡尔重构树)
题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...
- 【BZOJ5415】【NOI2018】归程(克鲁斯卡尔重构树)
[NOI2018]归程(克鲁斯卡尔重构树) 题面 洛谷 题解 我在现场竟然没有把这道傻逼题给切掉,身败名裂. 因为这题就是克鲁斯卡尔重构树的模板题啊 我就直接简单的说一下把 首先发现答案就是在只经过海 ...
- [note]克鲁斯卡尔重构树
克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...
- 洛谷P4768 [NOI2018]归程(克鲁斯卡尔重构树+最短路)
传送门 前置技能,克鲁斯卡尔重构树 我们按道路的高度建一个最大生成树,然后建好克鲁斯卡尔重构树 那么我们需要知道一颗子树内到1点距离最近是多少(除此之外到子树内任何一个点都不需要代价) 可以一开始直接 ...
随机推荐
- 深入理解幂等性及Restful风格API的幂等性问题详解
什么是幂等性 HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外).也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同. ...
- 论文翻译:2015_DNN-Based Speech Bandwidth Expansion and Its Application to Adding High-Frequency Missing Features for Automatic Speech Recognition of Narrowband Speech
论文地址:基于DNN的语音带宽扩展及其在窄带语音自动识别中加入高频缺失特征的应用 论文代码:github 博客作者:凌逆战 博客地址:https://www.cnblogs.com/LXP-Never ...
- 来简单说说var,let,const,function,import,class
一.var和let var已经在JavaScript中存在很长一段时间了,但是它存在了一些不足的地方,接下来我们就来看看吧 首先var存在变量提升,这是怎么一回事呢,我们看下面代码 为什么是它呢,是因 ...
- Maven jar包冲突
在pom.xml中引入一个依赖,maven会自动导入这个依赖的依赖,方便的同时也会造成jar包冲突: (1)A.B都依赖C,我们导入A(自动导入C).B(自动导入C),maven自动导入了2个C,到底 ...
- elsearch搜索引擎 + painless脚本语言入门
最近项目用到了elsearch,ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎. 自从版本6.0之后,其默认脚本语言变为 painless . ...
- node的httpserver简单创建
1.设计原则为文件夹名字可以依据资源来命名,静态资源统一命名 ps:路径中绝对和相对路径,依据server.js本身的位置而言 const http = require("http" ...
- cobaltstrike使用笔记2
0x01 cs服务端绕过流量检测 定义C2的通信格式,修改CS默认的流量特征 编写Profiles: 开源Profiles:https://github.com/rsmudge/Malleable-C ...
- 最小生成树算法总结(Kruskal,Prim)
今天复习最小生成树算法. 最小生成树指的是在一个图中选择n-1条边将所有n个顶点连起来,且n-1条边的权值之和最小.形象一点说就是找出一条路线遍历完所有点,不能形成回路且总路程最短. Kurskal算 ...
- 对象浅拷贝Object.assign
const target = { a: { b: { c: { d: 1 } }, e: 5, f: 6, h: 10 } } const source = { a: { b: { c: { d: 1 ...
- Python 测试代码 初学者笔记
单元测试 每完成一个单元测试,Python都会打印一个字符: 测试通过打印一个句点:测试引发错误打印E:测试导致断言失败打印F 模块unittest import unittest from name ...