BZOJ4771: 七彩树
题解: 对于每个节点 他只会对这个节点到根这条路径上的点产生贡献 所以我们考虑树链的并 找到每个节点能作用的深度最低的位置 然后对于深度建主席树,权值为dfs序的下标 通过set来维护树链的并 最后查询即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=1e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{ int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add( int x, int y){o->t=y;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1; char ch= getchar (); while (! isdigit (ch)){ if (ch== '-' )f=-1;ch= getchar ();} while ( isdigit (ch))x=x*10+ch- '0' ,ch= getchar (); return x*f; } typedef struct node{ int l,r,sum; }node; node d[MAXN*81]; int f[MAXN][21],dep[MAXN],p[MAXN],fp[MAXN],cnt,cnt1,rt[MAXN],a[MAXN],n,q,num[MAXN],id[MAXN]; set< int >s[MAXN]; set< int >::iterator ite,ip; void dfs( int x, int fa, int deep){ f[x][0]=fa;dep[x]=deep+1;p[x]=++cnt;fp[p[x]]=x;num[x]=1; link(x){ if (j->t!=fa)dfs(j->t,x,deep+1),num[x]+=num[j->t]; } } void dfs1( int x){ for ( int i=1;i<=20;i++)f[x][i]=f[f[x][i-1]][i-1]; link(x) if (j->t!=f[x][0])dfs1(j->t); } int Lca( int u, int v){ if (dep[u]<dep[v])swap(u,v); int tmp=dep[u]-dep[v]; inc(i,0,20) if (tmp&(1<<i))u=f[u][i]; if (u==v) return u; dec(i,20,0){ if (f[u][i]!=f[v][i])u=f[u][i],v=f[v][i]; } return f[u][0]; } void update( int &x, int y, int l, int r, int t, int vul){ x=++cnt1;d[x]=d[y];d[x].sum+=vul; if (l==r) return ; int mid=(l+r)>>1; if (t<=mid)update(d[x].l,d[y].l,l,mid,t,vul); else update(d[x].r,d[y].r,mid+1,r,t,vul); } int ans; void querty( int x, int y, int l, int r, int ql, int qr){ if (ql<=l&&r<=qr){ans+=d[y].sum-d[x].sum; return ;} int mid=(l+r)>>1; if (ql<=mid)querty(d[x].l,d[y].l,l,mid,ql,qr); if (qr>mid)querty(d[x].r,d[y].r,mid+1,r,ql,qr); } bool cmp( int aa, int bb){ return dep[aa]<dep[bb];} int main(){ int _=read(); while (_--){ cnt=cnt1=0;n=read();q=read(); memset (e,0, sizeof (e)); memset (h,0, sizeof (h));o=e; inc(i,1,n)id[i]=i,a[i]=read(),s[i].clear(); int u,v; inc(i,2,n)u=read(),add(i,u),add(u,i); dfs(1,0,0);dfs1(1); sort(id+1,id+n+1,cmp); int tot=1; inc(i,1,n){ rt[i]=++cnt1;d[rt[i]]=d[rt[i-1]]; while (tot<=n&&dep[id[tot]]<=i){ update(rt[i],rt[i],1,n,p[id[tot]],1); ite=s[a[id[tot]]].lower_bound(p[id[tot]]); int x=0,y=0; if (ite!=s[a[id[tot]]].begin())ip=ite,ip--,x=fp[(*ip)],update(rt[i],rt[i],1,n,p[Lca(id[tot],x)],-1); if (ite!=s[a[id[tot]]].end())ip=ite,y=fp[(*ip)],update(rt[i],rt[i],1,n,p[Lca(id[tot],y)],-1); if (x&&y)update(rt[i],rt[i],1,n,p[Lca(x,y)],1); s[a[id[tot]]].insert(p[id[tot]]);tot++; } } int res=0,x,d; while (q--){ x=read()^res;d=read()^res; ans=0;querty(rt[dep[x]-1],rt[min(dep[x]+d,n)],1,n,p[x],p[x]+num[x]-1);res=ans; printf ( "%d\n" ,res); } } } |
4771: 七彩树
Time Limit: 5 Sec Memory Limit: 256 MBSubmit: 1520 Solved: 432
[Submit][Status][Discuss]
Description
给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节
点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离
,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色
。请写一个程序,快速回答这些询问。
Input
第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
第二行包含n个正整数,其中第i个数为c[i](1<=c[i]<=n),分别表示每个节点的颜色。
第三行包含n-1个正整数,其中第i个数为f[i+1](1<=f[i]<i),表示节点i+1的父亲节点的编号。
接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
输入数据保证n和m的总和不超过500000。
Output
对于每个询问输出一行一个整数,即答案。
Sample Input
1
5 8
1 3 3 2 2
1 1 3 3
1 0
0 0
3 0
1 3
2 1
2 0
6 2
4 1
5 8
1 3 3 2 2
1 1 3 3
1 0
0 0
3 0
1 3
2 1
2 0
6 2
4 1
Sample Output
1
2
3
1
1
2
1
1
2
3
1
1
2
1
1
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理