BZOJ 4129 Haruna’s Breakfast ( 树上带修莫队 )
题面
求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述
分析
树上带修莫队板题,问题是怎么求最小的没出现过的权值。
因为只有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 ( 树上带修莫队 )的更多相关文章
- BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)
4129: Haruna’s Breakfast Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 835 Solved: 409[Submit][St ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)
BZOJ3585,BZOJ2120,BZOJ3757三合一. 对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队. 这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度. 剩下 ...
- BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
- 【BZOJ-3052】糖果公园 树上带修莫队算法
3052: [wc2013]糖果公园 Time Limit: 200 Sec Memory Limit: 512 MBSubmit: 883 Solved: 419[Submit][Status] ...
- LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
- BZOJ3052: [wc2013]糖果公园【树上带修莫队】
Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...
- luogu4074 [WC2013]糖果公园(树上带修莫队)
link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...
- BZOJ 3052 树上带修莫队
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
随机推荐
- 微软的一道网红Java面试题
题目: 给定一个int类型数组:int[] array = new int[]{12, 2, 3, 3, 34, 56, 77, 432}, 让该数组的每个位置上的值去除以首位置的元素,得到的结果,作 ...
- Maven打包成可执行JAR(带依赖包)
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> ...
- 【C++札记】类的分离式写法
介绍 类的分离式写法,使得代码更加规范,增强了阅读性. 分离式写法的规则: 1.类的变量:写在类的里面 2.成员函数:类中写函数的声明,函数的定义写在类体外. 3.写在类外函数定义时,类名前加限定(O ...
- python中列表之间求差集、交集、并集
求两个列表的交集.并集.差集 def diff(listA, listB): # 求交集的两种方式 retA = [i for i in listA if i in listB] retB = lis ...
- PHP关于VC11,VC9,VC6以及Thread Safe和Non Thread Safe版本选择的问题
这里是我在搭建php环境时收集的资料供大家参考: 现在PHP官网上下载PHP安装包都有VC11或VC9的字样,这是什么含义,我们应该下载哪种安装包更好呢?其实PHP官网给出了答案: VC6版本是使用V ...
- jvm垃圾回收器介绍
上篇文章中我们讨论了jvm的内存区域,这篇文章我们来讨论针对的内存区域的垃圾回收机制. 其实针对垃圾回收我们通常考虑三个问题:1.哪些内存需要回收?2.什么时候回收?3.如何回收?下面我们针对这三个问 ...
- android 仿微信朋友圈图片选择控件
调用方式(布局文件就是一个自定义控件): private ArrayList<String> selectedImages; @BindView(R.id.imagePicker) Ima ...
- 在论坛中出现的比较难的sql问题:6(动态行转列 考试科目、排名动态列问题)
原文:在论坛中出现的比较难的sql问题:6(动态行转列 考试科目.排名动态列问题) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路. 下面的几个问题,都是动态行转列的问题. ...
- [C#] LINQ之SelectMany和GroupJoin
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 在CentOS部署AspNetCore网站
前段时间某云服务器大促,就买了一台打算折腾一下,买了几个月,却啥也没做,就改了个初始密码.最近快到双十一了,另一家厂商相同配置的服务器价格又便宜了一大截,看来又得剁手了.从今年开始,搜索一下云服务器, ...