BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree
BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree
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
设dfn[i]为i的dfs序的编号。
那么每次相当于对所有dfn[x]<=dfn[y]<=son[x]且dep[y]-dep[x]<=L的点进行染色。
直接KDTree维护矩形染色即可。
代码:
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 <algorithm> using namespace std; #define N 100050 #define ls ch[p][0] #define rs ch[p][1] typedef long long ll; const int mod=1000000007; int head[N],to[N<<1],nxt[N<<1],C[N],n,T; int dfn[N],dep[N],mx[N][2],ch[N][2],mn[N][2],root,now,cov[N],son[N],cnt; inline void add( int u, int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } struct Point { int p[2]; bool operator < ( const Point &x) const { return p[now]==x.p[now]?p[!now]<x.p[!now]:p[now]<x.p[now]; } }a[N],b[N]; void pushup( int p, int x) { int i; for (i=0;i<2;i++) mx[p][i]=max(mx[p][i],mx[x][i]),mn[p][i]=min(mn[p][i],mn[x][i]); } void pushdown( int p) { if (cov[p]!=-1) { cov[ls]=cov[rs]=C[ls]=C[rs]=cov[p]; cov[p]=-1; } } int build( int l, int r, int type) { int mid=(l+r)>>1; now=type; nth_element(a+l,a+mid,a+r+1); int i; for (i=0;i<2;i++) mx[mid][i]=mn[mid][i]=a[mid].p[i]; if (l<mid) ch[mid][0]=build(l,mid-1,!type),pushup(mid,ch[mid][0]); if (r>mid) ch[mid][1]=build(mid+1,r,!type),pushup(mid,ch[mid][1]); return mid; } bool judge( int t1, int t2, int t3, int t4) { return (t1<t3||t1>t4)&&(t2<t3||t2>t4); } void update( int x, int y, int z, int w, int p, int c) { // printf("%d\n",p); // printf("%d %d %d %d\n",x,y,z,w); // a[x].mx[0] < bx || a[x].mn[0] > ex || a[x].mx[1] < by || a[x].mn[1] > ey if (mn[p][0]>=x&&mx[p][0]<=z&&mn[p][1]>=y&&mx[p][1]<=w) {cov[p]=C[p]=c; return ;} if (mx[p][0]<x||mn[p][0]>z||mx[p][1]<y||mn[p][1]>w) return ; pushdown(p); if (a[p].p[0]>=x&&a[p].p[0]<=z&&a[p].p[1]>=y&&a[p].p[1]<=w) C[p]=c; if (ls) update(x,y,z,w,ls,c); if (rs) update(x,y,z,w,rs,c); } int query( int x) { int p=root; now=0; while (1) { pushdown(p); if (b[x]<a[p]) p=ls; else if (a[p]<b[x]) p=rs; else return C[p]; now=!now; } } void dfs( int x, int y) { int i; dfn[x]=++dfn[0]; dep[x]=dep[y]+1; for (i=head[x];i;i=nxt[i]) { if (to[i]!=y) dfs(to[i],x); } son[x]=dfn[0]; } void solve() { int Q; memset (head,0, sizeof (head)); cnt=0; memset (ch,0, sizeof (ch)); dfn[0]=0; scanf ( "%d%*d%d" ,&n,&Q); int i,x,y; for (i=2;i<=n;i++) { scanf ( "%d" ,&x); add(x,i); add(i,x); } dfs(1,0); for (i=1;i<=n;i++) a[i].p[0]=dfn[i],a[i].p[1]=dep[i],cov[i]=-1,C[i]=1,b[i]=a[i]; root=build(1,n,0); int ans=0,z; // printf("%d %d %d\n",dfn[4],son[4],dep[4]); for (i=1;i<=Q;i++) { scanf ( "%d%d%d" ,&x,&y,&z); if (z) { update(dfn[x],dep[x],son[x],dep[x]+y,root,z); } else { ans=(ans+ll(i)*query(x)%mod)%mod; // printf("%d\n",query(x)); } } printf ( "%d\n" ,ans); } int main() { int T; scanf ( "%d" ,&T); while (T--) { solve(); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步