题目描述

给出一棵树,点有点权。支持两种操作:修改一个点的点权,查询链上mex。

输入

第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数。
第二行包括n个整数a1...an,代表每个结点的食材初始的美味度。
接下来n-1行,每行包括两个整数u,v,代表树上的一条边。
接下来m行,每行包括三个整数
0 u x 代表将结点u的食材的美味度修改为 x。
1 u v 代表询问以u,v 为端点的链的mex值。

输出

对于每次询问,输出该链的mex值。

样例输入

10 10
1 0 1 0 2 4 4 0 1 0
1 2
2 3
2 4
2 5
1 6
6 7
2 8
3 9
9 10
0 7 14
1 6 6
0 4 9
1 2 2
1 1 8
1 8 3
0 10 9
1 3 5
0 10 0
0 7 7

样例输出

0
1
2
2
3


题解

带修改树上莫队+分块

本题如果在链上并且不带修改的话就是 mex / Rmq Problem ,可以使用莫队算法+分块实现。

那么如果带单点修改并出到树上,则需要莫队算法的 带修改进化版+树上进化版 。带修改树上莫队的具体方法可以参考 糖果公园

于是直接树分块,按照左端点所在块、右端点所在块、时间(询问之前的修改次数)排序,暴力移动三个指针即可。显然大于n的权值可以看成n,于是对权值分块,对每个块维护块内有多少数出现过。查询时先查询块在找块内。

时间复杂度$O(n^{\frac 53})$

#include <cstdio>
#include <algorithm>
#define N 50010
using namespace std;
const int si = 2000 , sq = 200;
int a[N] , head[N] , to[N << 1] , next[N << 1] , cnt , fa[N][17] , deep[N] , log[N] , tot , sta[N] , top , bl[N] , num;
int cp[N] , ca[N] , cb[N] , vis[N] , buc[N] , sum[310] , ans[N];
struct data
{
int u , v , t , id;
bool operator<(const data &a)const {return bl[u] == bl[a.u] ? bl[v] == bl[a.v] ? t < a.t : bl[v] < bl[a.v] : bl[u] < bl[a.u];}
}q[N];
inline void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
int i , now = top;
for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(i = head[x] ; i ; i = next[i])
{
if(to[i] != fa[x][0])
{
fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
if(top - now >= si)
{
num ++ ;
while(top != now) bl[sta[top -- ]] = num;
}
}
}
sta[++top] = x;
}
inline int lca(int x , int y)
{
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if((1 << i) <= deep[x] - deep[y])
x = fa[x][i];
if(x == y) return x;
for(i = log[deep[x]] ; ~i ; i -- )
if((1 << i) <= deep[x] && fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i];
return fa[x][0];
}
inline void ins(int x)
{
sum[x / sq] += !buc[x] , buc[x] ++ ;
}
inline void del(int x)
{
buc[x] -- , sum[x / sq] -= !buc[x];
}
inline void rev(int x)
{
if(!vis[x]) ins(a[x]);
else del(a[x]);
vis[x] ^= 1;
}
int main()
{
int n , m , i , j , opt , x , y , un = 1 , vn = 1 , cn = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , a[i] = min(a[i] , n);
for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , log[i] = log[i >> 1] + 1;
dfs(1);
while(top) bl[sta[top -- ]] = num;
for(i = 1 ; i <= m ; i ++ )
{
scanf("%d%d%d" , &opt , &x , &y);
if(opt) q[i - cn].u = x , q[i - cn].v = y , q[i - cn].t = cn , q[i - cn].id = i - cn;
else y = min(y , n) , cp[++cn] = x , ca[cn] = a[x] , cb[cn] = a[x] = y;
}
m -= cn , sort(q + 1 , q + m + 1);
for(i = 1 ; i <= m ; i ++ )
{
x = lca(un , q[i].u);
for(j = un ; j != x ; j = fa[j][0]) rev(j);
for(j = q[i].u ; j != x ; j = fa[j][0]) rev(j);
un = q[i].u;
x = lca(vn , q[i].v);
for(j = vn ; j != x ; j = fa[j][0]) rev(j);
for(j = q[i].v ; j != x ; j = fa[j][0]) rev(j);
vn = q[i].v;
while(cn < q[i].t)
{
cn ++ , a[cp[cn]] = cb[cn];
if(vis[cp[cn]]) del(ca[cn]) , ins(cb[cn]);
}
while(cn > q[i].t)
{
if(vis[cp[cn]]) del(cb[cn]) , ins(ca[cn]);
a[cp[cn]] = ca[cn] , cn --;
}
x = lca(un , vn) , rev(x);
for(j = 0 ; sum[j] == sq ; j ++ );
for(j *= sq ; buc[j] ; j ++ );
ans[q[i].id] = j , rev(x);
}
for(i = 1 ; i <= m ; i ++ ) printf("%d\n" , ans[i]);
return 0;
}

【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块的更多相关文章

  1. 【bzoj3052】[wc2013]糖果公园 带修改树上莫队

    题目描述 给出一棵n个点的树,每个点有一个点权,点权范围为1~m.支持两种操作:(1)修改一个点的点权 (2)对于一条路径,求$\sum\limits_{i=1}^m\sum\limits_{j=1} ...

  2. BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]

    传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...

  3. UOJ 58 (树上带修改的莫队)

    UOJ 58 糖果公园 Problem : 给一棵n个点的树,每个点上有一种颜色,对于一条路径上的点,若 i 颜色第 j 次出现对该路径权值的贡献为 w[i] * c[j], 每次询问一条路径的权值, ...

  4. BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节 ...

  5. 【BZOJ】2120: 数颜色 带修改的莫队算法

    [题意]给定n个数字,m次操作,每次询问区间不同数字的个数,或修改某个位置的数字.n,m<=10^4,ai<=10^6. [算法]带修改的莫队算法 [题解]对于询问(x,y,t),其中t是 ...

  6. P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队

    \(\color{#0066ff}{ 题目描述 }\) 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支 ...

  7. UVA - 12345 带修改的莫队

    题意显然:给出初始序列,单点修改,区间查询元素的种类. 由于时限过宽,暴力可过. 比较优秀的解法应该是莫队. 带修改的莫队题解可以看https://www.luogu.org/blog/user126 ...

  8. codeforces 940F 带修改的莫队

    F. Machine Learning time limit per test 4 seconds memory limit per test 512 megabytes input standard ...

  9. Machine Learning CodeForces - 940F(带修改的莫队)

    题解原文地址:https://www.cnblogs.com/lujiaju6555/p/8468709.html 给数组a,有两种操作,1 l r查询[l,r]中每个数出现次数的mex,注意是出现次 ...

随机推荐

  1. MySQL在同一表格里把字段值(value)给另一字段(name)

    在最近的窗帘项目中,我需要增加新的计价方法,其中就有一个是在后台输入价格的: 数据表: 购买页面 点击提交订单 那么我要算出有遮光衬布物品的价格,就必须知道我在后台设置的价格是多少 所以上代码: $i ...

  2. 【linux运维递进】

    ================================云计算和虚拟化=================================== docker openstack svn git ...

  3. Flask初见

    Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSIG工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 .Flask使用 BSD 授权. Flask也被称为 “m ...

  4. Go语言中的UDP应用

    Go语言中的UDP应用 Go语言中使用UDP是很方便的,net包提供了UDP和TCP的功能,这里使用UDP做了一个UDP广播,然后接收各个设备的返回信息.实现起来很快,总体感觉比使用C#中的UDP更优 ...

  5. 【NOIP-2017PJ】图书管理员

    图书管理员 题目描述 图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个 正整数. 每位借书的读者手中有一个需求码,这个需求码也是一个正整数.如果一本书的图 书编码恰好以读者的需 ...

  6. 初步学习pg_control文件之四

    接前文,初步学习pg_control文件之三  继续分析 何时出现 DB_SHUTDOWNING状态: 在正常的shutdown的时候,需要进行checkpoint,所以就在此处,设置pg_contr ...

  7. C++11中decltype的使用

    The decltype type specifier yields the type of a specified expression. The decltype type specifier, ...

  8. 1321. [ZJOI2012] 灾难

    1321. [ZJOI2012] 灾难 ★★☆   输入文件:catas.in   输出文件:catas.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 阿米巴是小强的 ...

  9. Java:static的作用分析

    static表示“静态”或者“全局”的意思,但在Java中不能在所有类之外定义全局变量,只能通过在一个类中定义公用.静态的变量来实现一个全局变量. 一.静态变量 1. Java中存在两种变量,一种是s ...

  10. Messy Code in Windows Server 2008 R2 English Edition

          We always use Windows Server 2008 R2 English operation system. And it doesn't have any problem ...