题目描述

给出一棵树,点有点权。支持两种操作:修改一个点的点权,查询链上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. 如何解决thinkphp5中验证码常见问题?

    对于thinkphp如何实现验证码,我这里就不介绍了.直接看之前的文章 http://www.cnblogs.com/qqblog/p/6639419.html.下面,我能想出来的是,我自己在开发过程 ...

  2. scala成长之路(2)对象和类

    scala提供了一种特殊的定义单例的方法:object关键字 scala> object Shabi{ | val age = 0 | val name = "shabi" ...

  3. ubuntu配置机器学习环境(三) opencv 安装

    这里使用脚本安装 一些教程里使用cmake 安装,很容易出错的 使用github上的安装脚本,自动化安装 参考链接 Ubuntu $ cd Ubuntu/2.4 $ chmod +x * # 如果要安 ...

  4. python2.7入门---模块(Module)

        来,这次我们就看下Python 模块(Module).它是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句.模块让你能够有逻辑地组织你的 Pytho ...

  5. gp的纯属意外的意外

    一不小心,把方法都传过去了,一脸蒙蔽说的就是我,啊哈哈哈啊哈

  6. DDR分析与布线要求

    基本知识 Double Data Rate Synchronous Dynamic Random Access Memory 简称 DDR SDRAM 双倍数据率同步动态随机存取内存 DDR SDRA ...

  7. Hibernate-ORM:15.Hibernate中的Criteria查询

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲师Hibernate中的Criteria查询! 一,Criteria简介: 刚接触Hibernate ...

  8. Laravel框架

    curl操作: ===================================初始化$ch=curl_init() 设置请求的urlcurl_setopt($ch,CURLOPT_URL,&q ...

  9. MyEclipse - 问题集 - 创建Maven项目,JDK版本默认是1.5

    修改Maven的配置文件settings.xml,增加profile节点,如下所示: <profile> <id>jdk-1.8</id> <activati ...

  10. 给apk签名

    一.签名 把apk和签名文件放在jdk bin目录下,然后在jkd bin目录下执行以下代码: jarsigner -verbose -keystore xxx.keystore -signedjar ...