bzoj 4154: [Ipsc2015]Generating Synergy (KD-tree)
来源:互联网 发布:软件字体乱码 编辑:程序博客网 时间:2024/06/10 17:02
4154: [Ipsc2015]Generating Synergy
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 500 Solved: 200
[Submit][Status][Discuss]
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
Source
题解:KD-tree
其实这道题就是用KD-tree实现了一颗树套树,树套树的常数巨大,而且空间使用量也很感人。对于这道题的数据范围来说有点悬,而KD-tree虽然很暴力,但是一般的时间复杂度是低于理论复杂度的。
KD-tree的第一维表示的是dfs序,第二维表示的是点的深度。
查询的时候有点类似线段树的单点查询,不过因为每个节点都维护的是一个范围,所以无法直接确定在左右子树,只能两个子树都扫一下,找到就退出。
修改的时候如果整个区间都符合那么就打标机,否则暴力修改。
注意修改和查询的时候都要进行标记下放。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 200003 #define p 1000000007 #define LL long long using namespace std; int cmpd,n,m,q,tot,nxt[N],point[N],v[N],deep[N],l[N],r[N],pos[N],sz,root,T,c; struct data{ int d[2],mx[2],mn[2]; int l,r,mark,col; }now,tr[N]; bool operator<(data a,data b) { return a.d[cmpd]<b.d[cmpd]; } void add(int x,int y) { tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; //cout<<x<<" "<<y<<endl; } void dfs(int x,int fa) { deep[x]=deep[fa]+1; pos[x]=++sz; l[x]=sz; for (int i=point[x];i;i=nxt[i]) { if (v[i]==fa) continue; dfs(v[i],x); } r[x]=sz; } void update(int x) { int l=tr[x].l; int r=tr[x].r; for (int i=0;i<=1;i++) { if (l) tr[x].mx[i]=max(tr[x].mx[i],tr[l].mx[i]),tr[x].mn[i]=min(tr[x].mn[i],tr[l].mn[i]); if (r) tr[x].mx[i]=max(tr[x].mx[i],tr[r].mx[i]),tr[x].mn[i]=min(tr[x].mn[i],tr[r].mn[i]); } } int build(int l,int r,int d) { cmpd=d; int mid=(l+r)/2; nth_element(tr+l,tr+mid,tr+r+1); tr[mid].l=0; tr[mid].r=0; tr[mid].mark=0; for (int i=0;i<=1;i++) tr[mid].mx[i]=tr[mid].mn[i]=tr[mid].d[i]; if (l<mid) tr[mid].l=build(l,mid-1,d^1); if (r>mid) tr[mid].r=build(mid+1,r,d^1); //cout<<tr[mid].d[0]<<" "<<tr[tr[mid].l].d[0]<<" "<<tr[tr[mid].r].d[0]<<endl; update(mid); return mid; } bool check(int x) { if (now.mn[1]<=tr[x].mn[1]&&tr[x].mx[1]<=now.mx[1]&&now.mn[0]<=tr[x].mn[0]&&tr[x].mx[0]<=now.mx[0]) return true; return false; } bool find(int x){ if (now.mn[1]>=tr[x].mn[1]&&now.mx[1]<=tr[x].mx[1]&&now.mn[0]>=tr[x].mn[0]&&now.mx[0]<=tr[x].mx[0]) return true;return false;} int query(int x) { if (tr[x].mark) { tr[tr[x].l].mark=tr[x].mark,tr[tr[x].r].mark=tr[x].mark; tr[x].col=tr[x].mark; tr[x].mark=0; } if (now.d[0]==tr[x].d[0]) return tr[x].col; if (!tr[x].l&&!tr[x].r) return -1; int ans=-1; if (find(tr[x].l)&&tr[x].l) ans=query(tr[x].l); if (ans!=-1) return ans; if (find(tr[x].r)&&tr[x].r) ans=query(tr[x].r); return ans;} bool pd(int x) { int ans=0; for (int i=0;i<=1;i++) { bool mark=0; if (tr[x].mn[i]<=now.mn[i]&&now.mn[i]<=tr[x].mx[i]) mark=true; if (tr[x].mn[i]<=now.mx[i]&&now.mx[i]<=tr[x].mx[i]) mark=true; if (now.mn[i]<=tr[x].mn[i]&&tr[x].mn[i]<=now.mx[i]) mark=true; if (now.mn[i]<=tr[x].mx[i]&&tr[x].mx[i]<=now.mx[i]) mark=true; ans+=mark; } if (ans==2) return true;else return false; } void change(int x) { if (check(x)) { tr[x].mark=tr[x].col=now.col; return; } if (tr[x].mark) { tr[tr[x].l].mark=tr[x].mark,tr[tr[x].r].mark=tr[x].mark; tr[x].col=tr[x].mark; tr[x].mark=0; } if (now.mn[1]<=tr[x].d[1]&&tr[x].d[1]<=now.mx[1]&&now.mn[0]<=tr[x].d[0]&&tr[x].d[0]<=now.mx[0]) tr[x].col=now.col; if (pd(tr[x].l)) change(tr[x].l); if (pd(tr[x].r)) change(tr[x].r); } int main() { freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d",&T); while (T--) { tot=0; memset(point,0,sizeof(point)); scanf("%d%d%d",&n,&c,&q); for (int i=2;i<=n;i++) { int x; scanf("%d",&x); add(x,i); } sz=0; dfs(1,0); //for (int i=1;i<=n;i++) cout<<pos[i]<<" "<<deep[i]<<" "<<l[i]<<" "<<r[i]<<endl; for (int i=1;i<=n;i++) tr[i].d[0]=pos[i],tr[i].d[1]=deep[i],tr[i].col=1; root=build(1,n,0); LL ans=0; for (int i=1;i<=q;i++) { int x,l1,c; scanf("%d%d%d",&x,&l1,&c); if (c==0) { now.d[0]=pos[x]; now.d[1]=deep[x]; now.mn[0]=pos[x]; now.mx[0]=pos[x]; now.mn[1]=deep[x]; now.mx[1]=deep[x]; int t=query(root); //cout<<t<<endl; ans=(ans+(LL)i*t%p)%p; } else { now.mn[0]=l[x]; now.mx[0]=r[x]; now.mn[1]=deep[x]; now.mx[1]=deep[x]+l1; now.col=c; change(root); } } printf("%I64d\n",ans); } }
0 0
- bzoj 4154: [Ipsc2015]Generating Synergy (KD-tree)
- 【BZOJ】4154: [Ipsc2015]Generating Synergy【KD树】
- bzoj 4154: [Ipsc2015]Generating Synergy KDtree
- 4154: [Ipsc2015]Generating Synergy K-D tree
- BZOJ 4154(Generating Synergy-kd-tree代替树套树)
- [Ipsc2015]Generating Synergy K-D tree
- NKOJ 4345 (Ipsc2015)Generating Synergy (DFS序+kd树)
- 【IPSC2015】【BZOJ4154】Generating Synergy
- [bzoj4154][Ipsc2015]Generating Synergy
- BZOJ4154 [Ipsc2015]Generating Synergy
- BZOJ4154: [Ipsc2015]Generating Synergy
- 【38.05%】【BZOJ 4154】Generating Synergy
- BZOJ4154——IPSC2015 Generating Synergy
- bzoj 2850: 巧克力王国 (KD-tree)
- bzoj 4066: 简单题 (KD-tree)
- bzoj 2683: 简单题 (KD-tree)
- bzoj 2626: JZPFAR (KD-tree)
- [BZOJ][KD-tree]2626: JZPFAR
- 实验二.Linux系统分析实验
- spring原理_IOC详解
- Find The Multiple POJ
- POJ 3617 3069 贪心
- spring boot常用注解详解
- bzoj 4154: [Ipsc2015]Generating Synergy (KD-tree)
- Odyssey 2016
- ASP.NET页面指令
- matlab读取txt,excel文件数据,图中图,局部放大
- 使用Python编写的文件备份程序
- JVM内存模型
- Odyssey会议文章
- 解析txt文件,赋值结构体数组
- The 2008 NIST Speaker Recognition Evaluation