【BZOJ4154】[Ipsc2015]Generating Synergy KDtree
【BZOJ4154】[Ipsc2015]Generating Synergy
Description
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色
Input
第一行一个数T,表示数据组数
接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数
接下来一行n-1个数描述2..n的父节点
接下来q行每行三个数a,l,c
若c为0,表示询问a的颜色
否则将距离a不超过l的a的子节点染成c
Output
设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+...+z_q模10^9+7
Sample Input
1
4 3 7
1 2 2
3 0 0
2 1 3
3 0 0
1 0 2
2 0 0
4 1 1
4 0 0
4 3 7
1 2 2
3 0 0
2 1 3
3 0 0
1 0 2
2 0 0
4 1 1
4 0 0
Sample Output
32
HINT
第1,3,5,7的询问的答案分别为1,3,3,1,所以答案为 1*1+2*0+3*3+4*0+5*3+6*0+7*1=32.
数据范围:
对于100%的数据T<=6,n,m,c<=10^5,
1<=a<=n,0<=l<=n,0<=c<=c
题解:想了半天奇怪的做法,正解居然是KDtree?
KDtree的第一维是DFS序,第二维是深度,区间修改用打标记实现,查询时下传标记,剩下的就不用说了吧?
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 101 102 103 104 105 106 | #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const ll P=1000000007; const int maxn=100010; int n,m,D,rt,cnt; ll ans; int to[maxn],next[maxn],head[maxn],p[maxn],q[maxn],fa[maxn],L[2],R[2],dep[maxn],st[maxn],pos[maxn]; struct kd { int ls,rs,fa,tag,col,org,v[2],sm[2],sn[2]; kd(){} kd( int a, int b, int c){sm[0]=sn[0]=v[0]=a,sm[1]=sn[1]=v[1]=b,org=c,ls=rs=fa=0,tag=0,col=1;} }t[maxn]; bool cmp( const kd &a, const kd &b) { return (a.v[D]==b.v[D])?(a.v[D^1]<b.v[D^1]):(a.v[D]<b.v[D]); } inline int rd() { int ret=0,f=1; char gc= getchar (); while (gc< '0' ||gc> '9' ) { if (gc== '-' )f=-f; gc= getchar ();} while (gc>= '0' &&gc<= '9' ) ret=ret*10+gc- '0' ,gc= getchar (); return ret*f; } inline void add( int a, int b) { to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } void dfs( int x) { p[x]=++p[0]; for ( int i=head[x];i!=-1;i=next[i]) dep[to[i]]=dep[x]+1,dfs(to[i]); q[x]=p[0]; } inline void pushup( int x, int y) { t[x].sm[0]=max(t[x].sm[0],t[y].sm[0]); t[x].sn[0]=min(t[x].sn[0],t[y].sn[0]); t[x].sm[1]=max(t[x].sm[1],t[y].sm[1]); t[x].sn[1]=min(t[x].sn[1],t[y].sn[1]); } inline void pushdown( int x) { if (t[x].tag) { if (t[x].ls) t[t[x].ls].col=t[t[x].ls].tag=t[x].tag; if (t[x].rs) t[t[x].rs].col=t[t[x].rs].tag=t[x].tag; t[x].tag=0; } } int build( int l, int r, int d) { if (l>r) return 0; int mid=(l+r)>>1; D=d,nth_element(t+l,t+mid,t+r+1,cmp),pos[t[mid].org]=mid; t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1); if (t[mid].ls) t[t[mid].ls].fa=mid,pushup(mid,t[mid].ls); if (t[mid].rs) t[t[mid].rs].fa=mid,pushup(mid,t[mid].rs); return mid; } void updata( int x, int y) { if (!x||t[x].sn[0]>R[0]||t[x].sm[0]<L[0]||t[x].sn[1]>R[1]||t[x].sm[1]<L[1]) return ; pushdown(x); if (t[x].sm[0]<=R[0]&&t[x].sn[0]>=L[0]&&t[x].sm[1]<=R[1]&&t[x].sn[1]>=L[1]) { t[x].tag=t[x].col=y; return ; } if (t[x].v[0]<=R[0]&&t[x].v[0]>=L[0]&&t[x].v[1]<=R[1]&&t[x].v[1]>=L[1]) t[x].col=y; updata(t[x].ls,y),updata(t[x].rs,y); } inline int query( int x) { st[st[0]=1]=x; while (t[st[st[0]]].fa) st[st[0]+1]=t[st[st[0]]].fa,st[0]++; while (st[0]) pushdown(st[st[0]]),st[0]--; return t[x].col; } void work() { n=rd(),rd(),m=rd(); memset (head,-1, sizeof (head)),cnt=0,ans=0; int i,a,b,c; for (i=2;i<=n;i++) fa[i]=rd(),add(fa[i],i); dep[1]=1,dfs(1); for (i=1;i<=n;i++) t[i]=kd(p[i],dep[i],i); rt=build(1,n,0); for (i=1;i<=m;i++) { a=rd(),b=rd(),c=rd(); if (!c) ans=(ans+(ll)i*query(pos[a]))%P; else L[0]=p[a],R[0]=q[a],L[1]=dep[a],R[1]=dep[a]+b,updata(rt,c); } printf ( "%lld\n" ,ans); } int main() { int T=rd(); while (T--) work(); return 0; } //1 4 3 7 1 2 2 3 0 0 2 1 3 3 0 0 1 0 2 2 0 0 4 1 1 4 0 0 |
| 欢迎来原网站坐坐! >原文链接<
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步