题面

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

分析

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

因为只有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. [NOIP普及组2011]装箱问题

    目录 链接 博客链接 题目链接 题目内容 题目描述 格式 输入 输出 样例 输入 输出 前缀知识 题解 题目名称:装箱问题 来源:2011年NOIP普及组 链接 博客链接 CSDN 洛谷博客 题目链接 ...

  2. go 函数定义

    -------------------------------------------- package main import "fmt" func add(x int, y i ...

  3. 2019杭电多校一 K. Function (数论)

    大意: 给定$n(n\le 10^{21})$, 求$\sum\limits_{i=1}^n gcd(\lfloor\sqrt[3]{i}\rfloor,i)\mod 998244353$ 首先立方根 ...

  4. codefroce 854 A.Fraction

    题解:贪心,每次从能够出发的飞机中取一个最大的就好啦,用一个队列维护一下~ ac代码: #include <cstdio> #include <iostream> #inclu ...

  5. (十一)Activitivi5之流程控制网关:连线

    一.案例 1.1 需求 我们希望如果是重要情况才需要班主任审批,否则班长审批就行. 1.2 案例 当流程走到“班长审批”任务节点的时候,如果是一般情况,则如下: /** * 完成任务 */ @Test ...

  6. C#获取Excel表格所有sheet名(Epplus)

    原文:C#获取Excel表格所有sheet名(Epplus) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

  7. 关于ECharts甘特图的实现

    对于使用ECharts图表的步骤,每种图表都是一致的,相信大家也都了解 此处只分享甘特图的option,代码如下: option: { title: { text: '项目实施进度表', left: ...

  8. iOS 9.0中UIAlertController的用法。

    1.我为什么要写这篇博客记录它? 答:因为 UIAlertView和UIActionSheet 被划线了 苹果不推荐我们使用这两个类了,也不再进行维护和更新,为了以后方便使用我来记录一下.如图所示 正 ...

  9. python实践总结与反思

    2019.6.20 python近期实践总结与反思 记录一些这两天python犯的一些低级却易犯的错误.千万不要犯第二次啊!! 1. py文件名字问题 py文件命名不能和调用的模块名一样! 比如,我要 ...

  10. Linux学习之九-Linux系统定时任务

    Linux系统定时任务 在一些实际工作中需要机器在某个时间自动执行某个任务,不需要人为在此时刻参与,可以建立一个定时任务. crond 服务是linux下用来周期性的执行某种任务或等待处理某些事件的一 ...