[学习笔记]树上莫队
其实树上莫队是一个欧拉序而已嘛,像普通的莫队,特判一下出现过两次的值就行了
设 \(st_i\) 为 \(i\) 进栈的时间,\(ed_i\) 为 \(i\) 出栈的时间,\(dfn_x<dfn_y\) ,那么就可以分两种情况:
1、\(y\) 在 \(x\) 子树中,也就是 \(LCA(x,y)=x\),那么区间转化成 \([st_x,st_y]\)
2、\(y\) 不在 \(x\) 子树中,也就是 \(LCA(x,y)\not =x\),那么区间转化成 \([ed_x,st_y]\)
然后就是板子了
for(int i=1;i<=m;i++){x=read(),y=read();q[i].anc=LCA(x,y);q[i].id=i;if(x==q[i].anc||y==q[i].anc){q[i].anc=0;q[i].l=st[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];}else {q[i].l=ed[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];}
}
1、SP10707 COT2 - Count on a tree II
其实我国庆的时候就学了,只不过我一直 \(WA\)...后来从倍增换成树剖,重构一遍代码就 \(A\) 了
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];struct Query{int l,r,anc,id;
}q[maxn];bool cmp(Query a,Query b){if((a.l-1)/blo!=(b.l-1)/blo)return (a.l-1)/blo<(b.l-1)/blo;return a.r<b.r;
}inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}
inline void add(int x,int y){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}void dfs1(int x,int f){siz[x]=1;fa[x]=f;dep[x]=dep[f]+1;st[x]=++tim;p[tim]=x;int maxson=-1;for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==f) continue;dfs1(y,x);siz[x]+=siz[y];if(maxson<siz[y]){maxson=siz[y];son[x]=y;}}ed[x]=++tim;p[tim]=x;
}void dfs2(int x,int topf){top[x]=topf;if(son[x]) dfs2(son[x],topf);for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==fa[x]||y==son[x]) continue;dfs2(y,y);}
}int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}int update(int x){if(vis[x]){if(--cnt[a[x]]==0) now--;}else if(++cnt[a[x]]==1) now++;vis[x]^=1;
}int main()
{n=read(),m=read();blo=sqrt(n);for(int i=1;i<=n;i++) mp[i]=a[i]=read();sort(mp+1,mp+n+1);int t=unique(mp+1,mp+n+1)-mp-1;for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+t+1,a[i])-mp;int x,y;for(int i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}dfs1(1,0);dfs2(1,1);for(int i=1;i<=m;i++){x=read(),y=read();q[i].anc=LCA(x,y);q[i].id=i;if(x==q[i].anc||y==q[i].anc){q[i].anc=0;q[i].l=st[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];}else {q[i].l=ed[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];}}sort(q+1,q+m+1,cmp);int L=1,R=0;for(int i=1;i<=m;i++){while(R<q[i].r) update(p[++R]);while(R>q[i].r) update(p[R--]);while(L<q[i].l) update(p[L++]);while(L>q[i].l) update(p[--L]);if(q[i].anc) update(q[i].anc);ans[q[i].id]=now;if(q[i].anc) update(q[i].anc);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}
2、苹果树(本地Cena自测)
其实就是特判一下 \(cnt_a\) 和 \(cnt_b\)
只不过我非常傻,离散了一下颜色,就 \(GG\) 了
\(Code\ Below:\)
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];struct Query{int l,r,a,b,anc,id;
}q[maxn];bool cmp(Query a,Query b){if((a.l-1)/blo!=(b.l-1)/blo)return (a.l-1)/blo<(b.l-1)/blo;return a.r<b.r;
}inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}
inline void add(int x,int y){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}void dfs1(int x,int f){siz[x]=1;fa[x]=f;dep[x]=dep[f]+1;st[x]=++tim;p[tim]=x;int maxson=-1;for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==f) continue;dfs1(y,x);siz[x]+=siz[y];if(maxson<siz[y]){maxson=siz[y];son[x]=y;}}ed[x]=++tim;p[tim]=x;
}void dfs2(int x,int topf){top[x]=topf;if(son[x]) dfs2(son[x],topf);for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==fa[x]||y==son[x]) continue;dfs2(y,y);}
}int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}void update(int x){if(vis[x]){if(--cnt[a[x]]==0) now--;}else if(++cnt[a[x]]==1) now++;vis[x]^=1;
}int main()
{n=read(),m=read();blo=sqrt(2*n);for(int i=1;i<=n;i++) a[i]=read();int x,y;for(int i=1;i<=n;i++){x=read(),y=read();if(x&&y) add(x,y),add(y,x);}dfs1(1,0);dfs2(1,1);for(int i=1;i<=m;i++){x=read(),y=read(),q[i].a=read(),q[i].b=read();q[i].anc=LCA(x,y);q[i].id=i;if(x==q[i].anc||y==q[i].anc){q[i].anc=0;q[i].l=st[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];}else {q[i].l=ed[x];q[i].r=st[y];if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];}}sort(q+1,q+m+1,cmp);int L=1,R=0;for(int i=1;i<=m;i++){while(R<q[i].r) update(p[++R]);while(R>q[i].r) update(p[R--]);while(L<q[i].l) update(p[L++]);while(L>q[i].l) update(p[--L]);if(q[i].anc) update(q[i].anc);ans[q[i].id]=now;if(q[i].a!=q[i].b&&cnt[q[i].a]&&cnt[q[i].b]) ans[q[i].id]--;if(q[i].anc) update(q[i].anc);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0;
}
3、Haruna’s Breakfast
小知识:带修莫队块大小在 \(n^{\frac 23}\) 跑的最快……不过我不会证
本人错误点:莫队修改过来的时候应该先将修改的时间戳 \(+1\),再更新;莫队修改回去的时候应该先更新,再将修改的时间戳 \(-1\)
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],pos[maxn],val[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now,Cnum,Qnum,an;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];struct Query{int l,r,anc,pre,id;
}q[maxn];bool cmp(Query a,Query b){if((a.l-1)/blo!=(b.l-1)/blo)return (a.l-1)/blo<(b.l-1)/blo;if(a.r!=b.r) return a.r<b.r;return a.pre<b.pre;
}inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}
inline void add(int x,int y){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}void dfs1(int x,int f){siz[x]=1;fa[x]=f;dep[x]=dep[f]+1;st[x]=++tim;p[tim]=x;int maxson=-1;for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==f) continue;dfs1(y,x);siz[x]+=siz[y];if(maxson<siz[y]){maxson=siz[y];son[x]=y;}}ed[x]=++tim;p[tim]=x;
}void dfs2(int x,int topf){top[x]=topf;if(son[x]) dfs2(son[x],topf);for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==fa[x]||y==son[x]) continue;dfs2(y,y);}
}int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}inline void update(int x){if(a[x]<maxn){if(vis[x]){if(--cnt[a[x]]==0) now=min(now,a[x]);}else if(++cnt[a[x]]==1) while(cnt[now]) now++;}vis[x]^=1;
}inline void Del(int x){if(vis[x]&&a[x]<maxn) if(--cnt[a[x]]==0) now=min(now,a[x]);}
inline void Add(int x){if(vis[x]&&a[x]<maxn) if(++cnt[a[x]]==1) while(cnt[now]) now++;}int main()
{n=read(),m=read();blo=pow(2*n,0.666666);for(int i=1;i<=n;i++) a[i]=read();int opt,x,y;for(int i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}dfs1(1,0);dfs2(1,1);for(int i=1;i<=m;i++){opt=read(),x=read(),y=read();if(opt==0){pos[++Qnum]=x;val[Qnum]=y;}else {q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;if(x==q[Cnum].anc||y==q[Cnum].anc){q[Cnum].anc=0;q[Cnum].l=st[x];q[Cnum].r=st[y];if(q[Cnum].l>q[Cnum].r) q[Cnum].l=st[y],q[Cnum].r=st[x];}else {q[Cnum].l=ed[x];q[Cnum].r=st[y];if(q[Cnum].l>q[Cnum].r) q[Cnum].l=ed[y],q[Cnum].r=st[x];}}}sort(q+1,q+Cnum+1,cmp);int L=1,R=0;for(int i=1;i<=Cnum;i++){while(R<q[i].r) update(p[++R]);while(R>q[i].r) update(p[R--]);while(L<q[i].l) update(p[L++]);while(L>q[i].l) update(p[--L]);if(q[i].anc) update(q[i].anc);while(an<q[i].pre){an++;Del(pos[an]);swap(a[pos[an]],val[an]);Add(pos[an]);}while(an>q[i].pre){Del(pos[an]);swap(a[pos[an]],val[an]);Add(pos[an]);an--;}ans[q[i].id]=now;if(q[i].anc) update(q[i].anc);}for(int i=1;i<=Cnum;i++) printf("%d\n",ans[i]);return 0;
}
4、GT and trees
综合题,求树上路径待修改区间众数,不难想到带修树上莫队
然后就再记录一个 \(f[i]\) 表示区间出现 \(i\) 次的数的个数,\(add\) 没什么好说的,\(del\) 就暴力找,跟 \(mex\) 一样
\(Code\ Below:\)
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],vis[maxn],f[maxn],cnt[maxn],pos[maxn],val[maxn];
int Ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,Cnum,Qnum,ans,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];struct Query{int l,r,anc,pre,id;
}q[maxn];bool cmp(Query a,Query b){if((a.l-1)/blo!=(b.l-1)/blo)return (a.l-1)/blo<(b.l-1)/blo;if(a.r!=b.r) return a.r<b.r;return a.pre<b.pre;
}inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}
inline void add(int x,int y){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}void dfs1(int x,int f){siz[x]=1;fa[x]=f;dep[x]=dep[f]+1;st[x]=++tim;p[tim]=x;int maxson=-1;for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==f) continue;dfs1(y,x);siz[x]+=siz[y];if(maxson<siz[y]){maxson=siz[y];son[x]=y;}}ed[x]=++tim;p[tim]=x;
}void dfs2(int x,int topf){top[x]=topf;if(son[x]) dfs2(son[x],topf);for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==fa[x]||y==son[x]) continue;dfs2(y,y);}
}int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}inline void update(int x){if(vis[x]){if(--f[cnt[a[x]]--]==0) while(!f[ans]) ans--;}else if(++f[++cnt[a[x]]]==1) ans=max(ans,cnt[a[x]]);vis[x]^=1;
}inline void Add(int x){if(vis[x]) if(++f[++cnt[a[x]]]==1) ans=max(ans,cnt[a[x]]);}
inline void Del(int x){if(vis[x]) if(--f[cnt[a[x]]--]==0) while(!f[ans]) ans--;}int main()
{int T=read();while(T--){memset(head,0,sizeof(head));memset(son,0,sizeof(son));memset(vis,0,sizeof(vis));memset(f,0,sizeof(f));memset(cnt,0,sizeof(cnt));tim=tot=Cnum=Qnum=ans=now=0;n=read(),m=read();blo=pow(2*n,0.666666);int opt,x,y;for(int i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}for(int i=1;i<=n;i++) a[i]=read();dfs1(1,0);dfs2(1,1);for(int i=1;i<=m;i++){opt=read(),x=read(),y=read();if(opt==0) pos[++Qnum]=x,val[Qnum]=y;else {q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;if(x==q[Cnum].anc||y==q[Cnum].anc){q[Cnum].anc=0;if(st[x]<st[y]) q[Cnum].l=st[x],q[Cnum].r=st[y];else q[Cnum].l=st[y],q[Cnum].r=st[x];}else {if(ed[x]<st[y]) q[Cnum].l=ed[x],q[Cnum].r=st[y];else q[Cnum].l=ed[y],q[Cnum].r=st[x];}}}sort(q+1,q+Cnum+1,cmp);int L=1,R=0;for(int i=1;i<=Cnum;i++){while(R<q[i].r) update(p[++R]);while(R>q[i].r) update(p[R--]);while(L<q[i].l) update(p[L++]);while(L>q[i].l) update(p[--L]);if(q[i].anc) update(q[i].anc);while(now<q[i].pre){now++;Del(pos[now]);swap(a[pos[now]],val[now]);Add(pos[now]);}while(now>q[i].pre){Del(pos[now]);swap(a[pos[now]],val[now]);Add(pos[now]);now--;}Ans[q[i].id]=ans;if(q[i].anc) update(q[i].anc);}for(int i=1;i<=Cnum;i++) printf("%d\n",Ans[i]);}return 0;
}
5、[WC2013]糖果公园
树上带修莫队 我20分钟切掉的
其实差不多一个板子,不过我被卡常了,我 \(inline+register+O_2\) 才过,最大一个点 \(5136ms\)
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define res register int
#define ll long long
using namespace std;
const int maxn=100000+10;
int n,m,Q,c[maxn],v[maxn],w[maxn],vis[maxn],cnt[maxn],pos[maxn],val[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,Cnum,Qnum,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;ll Ans[maxn],ans;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];struct Query{int l,r,anc,pre,id;
}q[maxn];bool cmp(Query a,Query b){if((a.l-1)/blo!=(b.l-1)/blo)return (a.l-1)/blo<(b.l-1)/blo;if(a.r<b.r) return a.r<b.r;return a.pre<b.pre;
}inline int read(){register int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return (f==1)?x:-x;
}
inline void add(res x,res y){to[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}void dfs1(res x,res f){siz[x]=1;fa[x]=f;dep[x]=dep[f]+1;st[x]=++tim;p[tim]=x;int maxson=-1;for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==f) continue;dfs1(y,x);siz[x]+=siz[y];if(maxson<siz[y]){maxson=siz[y];son[x]=y;}}ed[x]=++tim;p[tim]=x;
}void dfs2(res x,res topf){top[x]=topf;if(son[x]) dfs2(son[x],topf);for(int i=head[x],y;i;i=nxt[i]){y=to[i];if(y==fa[x]||y==son[x]) continue;dfs2(y,y);}
}inline int LCA(res x,res y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}inline void update(res x){if(vis[x]){ans-=(ll)v[c[x]]*w[cnt[c[x]]--];}else ans+=(ll)v[c[x]]*w[++cnt[c[x]]];vis[x]^=1;
}inline void Del(res x){if(vis[x]) ans-=(ll)v[c[x]]*w[cnt[c[x]]--];}
inline void Add(res x){if(vis[x]) ans+=(ll)v[c[x]]*w[++cnt[c[x]]];}int main()
{n=read(),m=read(),Q=read();blo=pow(2*n,0.666666);for(res i=1;i<=m;i++) v[i]=read();for(res i=1;i<=n;i++) w[i]=read();res opt,x,y;for(res i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}dfs1(1,0);dfs2(1,1);for(res i=1;i<=n;i++) c[i]=read();for(res i=1;i<=Q;i++){opt=read(),x=read(),y=read();if(opt==0) pos[++Qnum]=x,val[Qnum]=y;else {q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;if(x==q[Cnum].anc||y==q[Cnum].anc){q[Cnum].anc=0;if(st[x]<st[y]) q[Cnum].l=st[x],q[Cnum].r=st[y];else q[Cnum].l=st[y],q[Cnum].r=st[x];}else {if(ed[x]<st[y]) q[Cnum].l=ed[x],q[Cnum].r=st[y];else q[Cnum].l=ed[y],q[Cnum].r=st[x];}}}sort(q+1,q+Cnum+1,cmp);res L=1,R=0;for(res i=1;i<=Cnum;i++){while(R<q[i].r) update(p[++R]);while(R>q[i].r) update(p[R--]);while(L<q[i].l) update(p[L++]);while(L>q[i].l) update(p[--L]);if(q[i].anc) update(q[i].anc);while(now<q[i].pre){now++;Del(pos[now]);swap(c[pos[now]],val[now]);Add(pos[now]);}while(now>q[i].pre){Del(pos[now]);swap(c[pos[now]],val[now]);Add(pos[now]);now--;}Ans[q[i].id]=ans;if(q[i].anc) update(q[i].anc);}for(res i=1;i<=Cnum;i++) printf("%lld\n",Ans[i]);return 0;
}
转载于:https://www.cnblogs.com/owencodeisking/p/10018392.html
[学习笔记]树上莫队相关推荐
- 【算法竞赛学习笔记】莫队算法-超优雅的暴力算法
title : 莫队算法 tags : ACM,暴力 date : 2021-10-30 author : Linno 普通莫队 常用操作:分块/排序/卡常/离散化等,直接上板子. luoguP270 ...
- 【学习笔记】莫队算法
莫队算法 确实是看过的最良心的讲解: https://www.cnblogs.com/CsOH/p/5904430.html 问题:有n个数组成一个序列,有m个形如询问L, R的询问,每次询问需要回答 ...
- 莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】
一.理解 我的理解就是巧妙的暴力,利用双指针以及分块思想,巧妙的移动双指针,时间复杂度可以达到O(NlogN). 强推博客:写的又好又全.链接 二.套路 1.普通莫队 [1]核心代码 bool cmp ...
- 莫队算法二(树上莫队cot2,Haruna’s Breakfast)
例一:不带修改 Count on a tree II Time Limit: 1207MS Memory Limit: 1572864KB 64bit IO Format: %lld & ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
- LG P4074 [WC2013] 糖果公园(带修莫队,树上莫队)
LG P4074 [WC2013] 糖果公园 Solution 树上带修莫队,主要还是复习带修莫队和树上莫队. 带修莫队: 带修莫队要先对lll分块的序号作为第一关键字,对rrr分块的序号作为第二关键 ...
- 【莫队/树上莫队/回滚莫队】原理详解及例题:小B的询问(普通莫队),Count on a tree II(树上莫队),kangaroos(回滚莫队)
文章目录 问题引入 介绍莫队算法及其实现过程 时间复杂度 莫队算法适用范围 莫队奇偶优化 普通莫队:小B的询问 树上莫队:SP10707 COT2 - Count on a tree II 回滚莫队: ...
- YBTOJ洛谷P4074:糖果公园(树上莫队)
文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...
- jzoj3360-[NOI2013模拟]苹果树【树上莫队,LCA】
正题 题目大意 一棵树上每个节点有不同的颜色,然后每次询问(x,y,a,b)(x,y,a,b)(x,y,a,b)表示将颜色aaa看为颜色bbb的情况下询问xxx到yyy有多少不种的颜色. 解题思路 数 ...
最新文章
- 利用gitHook实现自动部署
- 电流如何在导线中传播
- 【Google Play】正式版上架流程 ( 创建版本 | 设置国家地区 | 发布正式版 )
- 【自动驾驶】33.【图像坐标系】 到 【像素坐标系】 的度量单位变换、【英寸】、【感光芯片】
- springboot 使用interceptor 返回前端http状态码为0
- Citrix XenServer Workload Balancing 报告词汇表
- 为什么要娶就娶电力女?!
- 时间戳转换(各种格式的都有,年月日 时分秒 周)
- 计算机事业单位专技岗考什么区别,事业单位管理岗和专技岗的区别(从待遇等角度)...
- mock接口开发,excel(读,写,修改)
- 软考初级——操作系统
- 第一次写CSDN的博客
- upc组队赛5 Election of Evil【搜索】
- nero 刻录一张4g的服务器系统盘大概需要多长时间,刻录系统盘(如何刻录系统盘) 狸窝用户有福了:nero刻录系统盘...
- python中并集的符号_Python 集合set添加删除、交集、并集、集合操作符号
- JSON.parse解析失败(报错,出错)
- B站下载姿势合集——亲测
- 大数据风控系统主要功能分析
- 怎么撰写一份优秀的数据分析报告(二)
- HLS第三十八课(xfopencv,H文件和HPP文件的使用)