interlinkage:
https://jzoj.net/senior/#main/show/3175
description:
给定一棵N 个节点的树,标号从1~N。每个点有一个权值。要求维护两种操作:
1. C i x(0<=x<2^31) 表示将i 点权值变为x
2. Q i j x(0<=x<2^31) 表示询问i 到j 的路径上有多少个值为x的节点
solution:
- 链剖
- 把颜色离散化,对每种颜色分别搞一颗线段树
- 直接搞会炸空间,因此要动态开点
- 感觉树上莫队好像也可以
code
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> using namespace std; typedef long long ll; const int N=4e5+15; int n,q,tot,cnt,tim; int head[N],dep[N],siz[N],wson[N],fa[N],top[N],dfn[N],rt[N<<1],color[N]; int lx[N<<4],rx[N<<4],sum[N<<4]; ll a[N],b[N<<1]; struct EDGE { int to,nxt; }edge[N]; struct QUE { int op; int x,y; ll v; }t[N]; inline ll read() { char ch=getchar();ll s=0,f=1; while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) {s=(s<<3)+(s<<1)+ch-‘0‘;ch=getchar();} return s*f; } void add(int u,int v) { edge[++tot]=(EDGE){v,head[u]}; head[u]=tot; } void dfs1(int x,int pre) { dep[x]=dep[pre]+1;siz[x]=1;fa[x]=pre; for (int i=head[x];i;i=edge[i].nxt) { int y=edge[i].to; if (y==pre) continue; dfs1(y,x); siz[x]+=siz[y]; if (!wson[x]||siz[wson[x]]<siz[y]) wson[x]=y; } } void dfs2(int x,int tp) { top[x]=tp;dfn[x]=++tim; if (wson[x]) dfs2(wson[x],tp); for (int i=head[x];i;i=edge[i].nxt) { int y=edge[i].to; if (y==fa[x]||y==wson[x]) continue; dfs2(y,y); } } void upd(int o) { sum[o]=sum[lx[o]]+sum[rx[o]]; } void update(int &o,int l,int r,int pos,int x) { if (!o) o=++cnt; if (l==r) { sum[o]+=x; return; } int mid=l+r>>1; if (pos<=mid) update(lx[o],l,mid,pos,x); else update(rx[o],mid+1,r,pos,x); upd(o); } void change(int x,int v) { if (color[x]) { update(rt[color[x]],1,n,dfn[x],-1); } color[x]=v; update(rt[v],1,n,dfn[x],1); } int query(int o,int l,int r,int x,int y) { if (!o) return 0; if (l>=x&&r<=y) return sum[o]; int mid=l+r>>1,re=0; if (x<=mid) re+=query(lx[o],l,mid,x,y); if (y>mid) re+=query(rx[o],mid+1,r,x,y); return re; } int query_path(int x,int y,int v) { int res=0; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); res+=query(rt[v],1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if (dep[x]<dep[y]) swap(x,y); res+=query(rt[v],1,n,dfn[y],dfn[x]); return res; } int main() { //freopen("tree.in","r",stdin); n=read();q=read(); int len=0; for (int i=1;i<=n;i++) a[i]=read(),b[++len]=a[i]; for (int i=1;i<n;i++) { int u=read(),v=read(); add(u,v);add(v,u); } dfs1(1,0); dfs2(1,1); char s[5]; for (int i=1;i<=q;i++) { scanf("%s",s); if (s[0]==‘C‘) { t[i].op=1; t[i].x=read();t[i].v=read(); } if (s[0]==‘Q‘) { t[i].op=2; t[i].x=read();t[i].y=read();t[i].v=read(); } b[++len]=t[i].v; } sort(b+1,b+1+len); len=unique(b+1,b+1+len)-b-1; for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+len,a[i])-b; for (int i=1;i<=q;i++) t[i].v=lower_bound(b+1,b+1+len,t[i].v)-b; for (int i=1;i<=n;i++) change(i,a[i]); for (int i=1;i<=q;i++) { if (t[i].op==1) { change(t[i].x,t[i].v); } if (t[i].op==2) { printf("%d\n",query_path(t[i].x,t[i].y,t[i].v)); } } return 0; }
原文地址:https://www.cnblogs.com/xxzh/p/10677655.html
时间: 2024-11-08 07:48:25