bzoj4129 Haruna’s Breakfast

Description

Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵树上,每个结点都有一样食材,Shimakaze要考验一下她。

每个食材都有一个美味度,Shimakaze会进行两种操作:

1、修改某个结点的食材的美味度。

2、对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少。即mex值。

请你帮帮Haruna吧。

Input

第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数。

第二行包括n个整数a1...an,代表每个结点的食材初始的美味度。

接下来n-1行,每行包括两个整数u,v,代表树上的一条边。

接下来m 行,每行包括三个整数

0 u x 代表将结点u的食材的美味度修改为 x。

1 u v 代表询问以u,v 为端点的链的mex值。

Output

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

Sample Input

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

Sample Output

0
1
2
2
3

HINT

1<=n<=5*10^4

1<=m<=5*10^4

0<=ai<=10^9

正解:树上带修改莫队+分块。

我只是感觉自己可能会忘记套路然后就又做了一道题。。

这题莫队的思路还是比较显然的,问题主要是如何查询。

我们把权值按照根号$n$分块。很显然,$mex<=n$,所以我们只需要把$<=n$的数标记就行了。

查询时我们从小到大枚举每一个块,如果当前这个块没有满,那么再枚举块内的每一个元素,这样我们就能很方便地找到答案了。

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <vector>
  9 #include <cmath>
 10 #include <queue>
 11 #include <stack>
 12 #include <map>
 13 #include <set>
 14 #define inf (1<<30)
 15 #define N (100010)
 16 #define il inline
 17 #define RG register
 18 #define ll long long
 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 20
 21 using namespace std;
 22
 23 struct upd{ int u,v,x; }q1[N];
 24 struct que{ int i,tim,u,v; }q2[N];
 25 struct edge{ int nt,to; }g[2*N];
 26
 27 int head[N],top[N],fa[N],son[N],dep[N],dfn[N],sz[N],bl[N],st[N],vis[N],val[N],sum[N],la[N],a[N],ans[N],n,m,num,Q1,Q2,Tp,Lca,cnt,Bl,totb,block;
 28
 29 il int gi(){
 30     RG int x=0,q=1; RG char ch=getchar();
 31     while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();
 32     if (ch==‘-‘) q=-1,ch=getchar();
 33     while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();
 34     return q*x;
 35 }
 36
 37 il void insert(RG int from,RG int to){
 38     g[++num]=(edge){head[from],to},head[from]=num; return;
 39 }
 40
 41 il int cmp(const que &a,const que &b){
 42     if (bl[a.u]==bl[b.u] && bl[a.v]==bl[b.v]) return a.tim<b.tim;
 43     if (bl[a.u]==bl[b.u]) return bl[a.v]<bl[b.v]; return bl[a.u]<bl[b.u];
 44 }
 45
 46 il void dfs1(RG int x,RG int p){
 47     dep[x]=dep[p]+1,fa[x]=p,sz[x]=1; RG int v;
 48     for (RG int i=head[x];i;i=g[i].nt){
 49     v=g[i].to; if (v==p) continue;
 50     dfs1(v,x),sz[x]+=sz[v];
 51     if (sz[son[x]]<=sz[v]) son[x]=v;
 52     }
 53     return;
 54 }
 55
 56 il void dfs2(RG int x,RG int p,RG int anc){
 57     top[x]=anc,dfn[x]=++cnt; RG int tp=Tp,v;
 58     if (son[x]) dfs2(son[x],x,anc); if (Tp-tp>block) ++totb;
 59     while (Tp-tp>block) bl[st[Tp--]]=totb;
 60     for (RG int i=head[x];i;i=g[i].nt){
 61     v=g[i].to; if (v==p || v==son[x]) continue;
 62     tp=Tp,dfs2(v,x,v); if (Tp-tp>block) ++totb;
 63     while (Tp-tp>block) bl[st[Tp--]]=totb;
 64     }
 65     st[++Tp]=x; return;
 66 }
 67
 68 il int lca(RG int u,RG int v){
 69     while (top[u]!=top[v]){
 70     if (dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]];
 71     }
 72     return dep[u]<dep[v] ? u : v;
 73 }
 74
 75 il void update(RG int x){
 76     if (!vis[x]){
 77     vis[x]=1; if (a[x]>n) return;
 78     ++val[a[x]]; if (val[a[x]]==1) ++sum[a[x]/Bl];
 79     } else{
 80     vis[x]=0; if (a[x]>n) return;
 81     --val[a[x]]; if (!val[a[x]]) --sum[a[x]/Bl];
 82     }
 83     return;
 84 }
 85
 86 il void modify(RG int x,RG int v){
 87     if (!vis[x]) a[x]=v; else update(x),a[x]=v,update(x); return;
 88 }
 89
 90 il void change(RG int u,RG int v){
 91     while (u!=v){
 92     if (dep[u]>dep[v]) update(u),u=fa[u]; else update(v),v=fa[v];
 93     }
 94     return;
 95 }
 96
 97 il int query(){
 98     for (RG int i=0;;++i)
 99     if (sum[i]!=Bl) for (RG int j=i*Bl;;++j) if (!val[j]) return j;
100 }
101
102 il void work(){
103     n=gi(),m=gi(),block=pow(n,0.6),Bl=sqrt(n);
104     for (RG int i=1;i<=n;++i) a[i]=gi(),la[i]=a[i];
105     for (RG int i=1,u,v;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u);
106     dfs1(1,0),dfs2(1,0,1),cnt=0; if (Tp) ++totb; while (Tp) bl[st[Tp--]]=totb;
107     for (RG int i=1,op,u,v;i<=m;++i){
108     op=gi(),u=gi(),v=gi();
109     if (!op)  q1[++Q1]=(upd){u,v,la[u]},la[u]=v;
110     else{ if (dfn[u]>dfn[v]) swap(u,v); q2[++Q2]=(que){Q2,Q1,u,v}; }
111     }
112     sort(q2+1,q2+Q2+1,cmp);
113     while (cnt<q2[1].tim) ++cnt,modify(q1[cnt].u,q1[cnt].v);
114     change(q2[1].u,q2[1].v),Lca=lca(q2[1].u,q2[1].v);
115     update(Lca),ans[q2[1].i]=query(),update(Lca);
116     for (RG int i=2;i<=Q2;++i){
117     while (cnt<q2[i].tim) ++cnt,modify(q1[cnt].u,q1[cnt].v);
118     while (cnt>q2[i].tim) modify(q1[cnt].u,q1[cnt].x),--cnt;
119     change(q2[i-1].u,q2[i].u),change(q2[i-1].v,q2[i].v);
120     Lca=lca(q2[i].u,q2[i].v),update(Lca),ans[q2[i].i]=query(),update(Lca);
121     }
122     for (RG int i=1;i<=Q2;++i) printf("%d\n",ans[i]); return;
123 }
124
125 int main(){
126     File("mex");
127     work();
128     return 0;
129 }
时间: 2024-12-07 08:42:08

bzoj4129 Haruna’s Breakfast的相关文章

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

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每次询问区间 \([l, r]\) 中元素的最小没有出现的自然数. 这个弱化的版本可以用离线+线段树二分水掉.但是这个做法显然不太好搬到树上做. 上面的弱化版还有一个莫队做法:可以用莫队维护出来每一个区间的每一个数的出现为次数.把出现过的数通过分块表示出来,于是查询的时候枚举每一个块,寻找第一个不满的

【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define N 50001 int v[N<<1],en,first[N],next[N<<1]; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } in

[BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)

Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵 树上,每个结点都有一样食材,Shimakaze要考验一下她. 每个食材都有一个美味度,Shimakaze会进行两种操作: 1.修改某个结点的食材的美味度. 2.对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少.即mex值. 请你帮帮Haruna吧. Solution 树上带修改莫队 统计答案的时候也分块查询,找到第一个没满的块开始一个一个找 #include<i

BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块

题目大意:给定一棵树,每个点有一个非负点权,支持下列操作 1.修改某个点的点权 2.查询某条链上的mex 考虑链上不带修改的版本,我们可以用莫队+分块来搞(链接戳这里) 现在到了树上带修改,果断糖果公园 本来抱着逗比的心态写了一发结果1.4s过了 跟糖果公园的80s完全不成正比啊0.0 #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <

【算法总结】根号算法相关

[莫队算法] [相关资料] <[莫队算法]> [相关题目] 1.[bzoj2038][2009国家集训队]小Z的袜子(hose) 题意:给出n个数与m个区间,在每个区间内选出两个数,求选出的两个数相等的概率. 分析:hzwerの博客 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #define LL long long 6 usin

湘大OJ1179Bird&#39;s Breakfast(dp)

题目描述 又是美好的一天,小鸟Jelly早早地起床,将要出门觅食.谁说没有天上掉馅饼的事,当Jelly出门时,惊奇地发现自己面前,N条悲催的小虫整齐地排成一排等待着Jelly享用.Jelly将这些虫标上序号1..N,当然,Jelly的警惕性还是很高的,他认为选择任意两条相邻的小虫i和i+1是危险的,但一条小虫都不吃显然是不现实的(p.s.因为会挨一天的饿-),吃多吃少无所谓.所以请你告诉Jelly它共有多少种选择方式. 输入 有多组输入数据, 每组输入数据一行,为N(1< N<=100000)

Breakfast or lunch?

原文 It was Sunday. I never get up early on Sundays. I sometimes stay in bed until lunchtime. Last Sunday I got up very late. I looked out of the window. It was dark outside. "What a day!" I thought. "It's raining again." Just then, the

L2,breakfast or lunch

express: what a day多么糟糕的天气 I‘m coming to see you我将要来看你 what a lot of trouble he is causing他犯了多少错误啊 word: nephew 侄子,外甥 sentence: I have just arrived by train. 词汇细看: ring, 鸣,响,发出声音 the telephone rang 打电话 please ring me late repeat 重复,及物动词vt,will you re

BZOJ4129(树上带修莫队)

树上莫队的基本思路是把树按dfs序分块,然后先按x所在块从小到大排序,再按y所在块从小到大排序,处理询问即可. 这道题带修改,再加一个时间维即可. 时间复杂度据说是$n^{\frac53}$,不知道是为什么. (块大小改成3也过了什么鬼..) #include <cstdio> #include <algorithm> using namespace std; const int N=50005,M=100005,B=1357,T=223; int n,m,e,x,y,t,tp,o