题面

求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述

分析

树上带修莫队板题,问题是怎么求最小的没出现过的权值。

因为只有nnn个点,所以没出现过的最小值一定在[0,n][0,n][0,n]内,所以大于nnn的无需维护。那么我们就值域分块,每n\sqrt nn​个数开一个数组,那么从小到大枚举块,如果当前块没有满那么就在这个块里查找,每次查找时间复杂度为O(n)O(\sqrt n)O(n​)。因为n,mn,mn,m值域相同,所以总时间复杂度为O(n53(莫队)+nn(分块查询)+nlogn(排序))O(n^{\frac 53}(莫队)+n\sqrt n(分块查
询)+nlogn(排序))O(n35​(莫队)+nn​(分块查询)+nlogn(排序))

  • 我用的是倍增求LCA

CODE

#include <bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &num) {
char ch; while((ch=getchar())<'0'||ch>'9');
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
}
const int MAXN = 50005;
int n, m, TreeB, ValB, TIMES, cntq, cntc;
int a[MAXN], la[MAXN], bel[MAXN], ans[MAXN];
struct QUERY {
int u, v, t, id;
inline bool operator <(const QUERY &o)const {
return bel[u] == bel[o.u] ? (bel[v] == bel[o.v] ? t < o.t : bel[v] < bel[o.v]) : bel[u] < bel[o.u];
}
}Q[MAXN];
struct CHANGE { int i, u, v; }C[MAXN];
int fir[MAXN], to[MAXN<<1], nxt[MAXN<<1], cnt;
inline void add(int u, int v) { to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; }
int stk[MAXN], f[MAXN][16], dep[MAXN], dfn[MAXN], tmr, tot, top; inline void dfs(int u, int ff) {
int bot = top; dfn[u] = ++tmr;
dep[u] = dep[f[u][0]=ff] + 1;
for(int i = fir[u]; i; i = nxt[i])
if(to[i] != ff) {
dfs(to[i], u);
if(top-bot > TreeB) {
++tot;
while(top > bot) bel[stk[top--]] = tot;
}
}
stk[++top] = u;
} inline void Pre() {
for(int j = 1; j < 16; ++j)
for(int i = 1; i <= n; ++i)
f[i][j] = f[f[i][j-1]][j-1];
} bool vis[MAXN]; int sz[MAXN], val[MAXN]; inline int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
for(int j = 0; j < 16; ++j)
if((dep[u]-dep[v])&(1<<j)) u = f[u][j];
if(u == v) return u;
for(int j = 15; ~j; --j)
if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
return f[u][0];
} inline void upd(int i) {
if(!vis[i]) {
vis[i] = 1; if(a[i] > n) return;
if(++val[a[i]] == 1) ++sz[a[i]/ValB];
}
else {
vis[i] = 0; if(a[i] > n) return;
if(--val[a[i]] == 0) --sz[a[i]/ValB];
}
} inline void rev(int u, int v) {
while(u != v) {
if(dep[u] < dep[v]) swap(u, v);
upd(u), u = f[u][0];
}
}
inline void modify(int i, int col) {
if(!vis[i]) { a[i] = col; return; }
upd(i), a[i] = col, upd(i);
}
inline int solve() {
for(int i = 0; ; ++i) if(sz[i] != ValB)
for(int j = i*ValB; ; ++j) if(!val[j])
return j;
} int main () {
read(n), read(m), TreeB = int(pow(n, 0.67)), ValB = int(sqrt(1.0*n));
for(int i = 1; i <= n; ++i) read(a[i]), la[i] = a[i];
for(int i = 1, u, v; i < n; ++i) read(u), read(v), add(u, v), add(v, u);
for(int i = 1, opt, x, y; i <= m; ++i) {
read(opt), read(x), read(y);
if(!opt) C[++cntc] = (CHANGE){ x, la[x], y }, la[x] = y;
else {
if(dfn[x] > dfn[y]) swap(x, y);
Q[++cntq] = (QUERY){ x, y, cntc, cntq };
}
}
dfs(1, 0); if(top) ++tot; while(top) bel[stk[top--]] = tot; Pre();
sort(Q + 1, Q + cntq + 1);
while(TIMES < Q[1].t) ++TIMES, modify(C[TIMES].i, C[TIMES].v);
rev(Q[1].u, Q[1].v); int LCA = lca(Q[1].u, Q[1].v);
upd(LCA), ans[Q[1].id] = solve(), upd(LCA);
for(int i = 2; i <= cntq; ++i) {
while(TIMES < Q[i].t) ++TIMES, modify(C[TIMES].i, C[TIMES].v);
while(TIMES > Q[i].t) modify(C[TIMES].i, C[TIMES].u), --TIMES;
rev(Q[i-1].u, Q[i].u), rev(Q[i-1].v, Q[i].v), LCA = lca(Q[i].u, Q[i].v);
upd(LCA), ans[Q[i].id] = solve(), upd(LCA);
}
for(int i = 1; i <= cntq; ++i)
printf("%d\n", ans[i]);
return 0;
}

BZOJ 4129 Haruna’s Breakfast ( 树上带修莫队 )的更多相关文章

  1. BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)

    4129: Haruna’s Breakfast Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 835  Solved: 409[Submit][St ...

  2. bzoj4129 Haruna’s Breakfast 树上带修莫队+分块

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...

  3. [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)

    BZOJ3585,BZOJ2120,BZOJ3757三合一. 对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队. 这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度. 剩下 ...

  4. BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)

    题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...

  5. 【BZOJ-3052】糖果公园 树上带修莫队算法

    3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MBSubmit: 883  Solved: 419[Submit][Status] ...

  6. LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)

    传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...

  7. BZOJ3052: [wc2013]糖果公园【树上带修莫队】

    Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...

  8. luogu4074 [WC2013]糖果公园(树上带修莫队)

    link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...

  9. BZOJ 3052 树上带修莫队

    思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...

随机推荐

  1. [转帖]Linux - NetworkManager网络管理工具

    Linux - NetworkManager网络管理工具 linux运维菜 发布时间:18-10-3020:32优质原创作者 简介 网络管理器(NetworManager)是检测网络.自动连接网络的程 ...

  2. windows使用sqlpus连接oracle 数据库

    1.先安装好Instant Client程序. 2.打开cmd 执行sqlplus命令,如果出现如下图 2.说明需要把oracle install 的bin目类 添加系统环境path中,如下图添加环境 ...

  3. (十四)JDBC入门

    目录 什么是JDBC 操作JDBC的步骤 DriverManager对象 数据库URL Connection对象 Statement对象 ResultSet对象 常用数据类型转换表 释放资源 SQL注 ...

  4. 剑指offer60:把二叉树打印成多行。上到下按层打印二叉树。

    1 题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 2 思路和方法 vector变量存储每一层的元素vector<vector<int> > ans ...

  5. Scratch运动模块——有趣的弹球游戏(一)

    大家好!我是蓝老师,有了前几期Scratch的基础,相信大家早已摩拳擦掌,跃跃欲试了,甚至还有些小伙伴已经编写了非常不错的程序. 学习编程就是这样不断探索.主动思考.解决问题的过程. 本期内容: 课程 ...

  6. 牛客 82E 无向图中的最短距离 (bitset,bfs)

    有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi) 令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf 每次查询图中 ...

  7. C# 对象互转

    /// <summary> /// 适用于初始化新实体 /// </summary> static public T RotationMapping<T, S>(S ...

  8. Java InterpolationSearch

    Java InterpolationSearch /** * <html> * <body> * <P> Copyright 1994-2018 JasonInte ...

  9. dotnetcore下解压zip文件,解决中文文件名乱码问题

    (迄今为止网上那些说的用Encoding.Default解决中文文件名乱码的都不能真正解决问题!) 1.在程序开始处 Encoding.RegisterProvider(CodePagesEncodi ...

  10. 学HTML第二晚 登录框的制作

    进天来弄个登录框 首先,登录框要有登录的账号.密码.和确定.取消的,密码也是要隐藏的. 然后,我们就做: 这是理想中的样子,有了想法,就开始写了 <!dotcype html> <h ...