以深度建立线段树,线段树父亲节点向儿子节点连边,然后用线段树合并可以得到任何一个点子树的线段树,只需向对应节点的线段树中的$O(\log n)$个点连边即可。为了保证连边关系不发生混乱,线段树需要进行可持久化。

这样建图,点数和边数都是$O(n\log n)$级别的,再求出强连通分量,用排列组合求出答案即可。

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstdlib>
const int N=100010,M=4000000,E=6000000;
int Case,n,i,x,y,f[M],d[N],root[N],fin[N],l[M],r[M],tot;
int gt[N],nxtt[N],vt[N],edt;
int ga[N],nxta[N],va[N],la[N],ra[N],eda;
int g[2][M],v[2][E],nxt[2][E],ed;
int q[M],t,vis[M],cnt[M];
long long ans;
void add(int x,int y){
vt[++edt]=y;
nxtt[edt]=gt[x];
gt[x]=edt;
}
void addask(int x,int y,int l,int r){
va[++eda]=y;
la[eda]=l;
ra[eda]=r<n?r:n;
nxta[eda]=ga[x];
ga[x]=eda;
}
void addedge(int x,int y){
if(!y)return;
v[0][++ed]=y;nxt[0][ed]=g[0][x];g[0][x]=ed;
v[1][ed]=x;nxt[1][ed]=g[1][y];g[1][y]=ed;
}
int merge(int x,int y,int a,int b){
if(!x)return y;
if(!y)return x;
int z=++tot;
if(a==b){
addedge(z,x);
addedge(z,y);
return z;
}
int mid=(a+b)>>1;
addedge(z,l[z]=merge(l[x],l[y],a,mid));
addedge(z,r[z]=merge(r[x],r[y],mid+1,b));
return z;
}
int build(int a,int b,int c){
int x=++tot;
if(a==b)return x;
int mid=(a+b)>>1;
if(c<=mid)addedge(x,l[x]=build(a,mid,c));else addedge(x,r[x]=build(mid+1,b,c));
return x;
}
void ask(int x,int a,int b,int c,int d,int p){
if(!x)return;
if(c<=a&&b<=d){
addedge(p,x);
return;
}
int mid=(a+b)>>1;
if(c<=mid&&l[x])ask(l[x],a,mid,c,d,p);
if(d>mid&&r[x])ask(r[x],mid+1,b,c,d,p);
}
void dfs(int x){
for(int i=gt[x];i;i=nxtt[i]){
dfs(vt[i]);
root[x]=merge(root[x],root[vt[i]],1,n);
}
for(int i=ga[x];i;i=nxta[i])ask(root[x],1,n,la[i],ra[i],va[i]);
}
void dfs1(int x){
vis[x]=1;
for(int i=g[0][x];i;i=nxt[0][i])if(!vis[v[0][i]])dfs1(v[0][i]);
q[++t]=x;
}
void dfs2(int x,int y){
vis[x]=0,f[x]=y;
for(int i=g[1][x];i;i=nxt[1][i])if(vis[v[1][i]])dfs2(v[1][i],y);
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=2;i<=n;i++)scanf("%d",&f[i]),add(f[i],i);
for(i=1;i<=n;i++){
d[i]=d[f[i]]+1;
root[i]=build(1,n,d[i]);
fin[i]=tot;
}
for(i=1;i<=n;i++)scanf("%d%d",&x,&y),addask(x,fin[i],d[x],d[x]+y);
dfs(1);
for(i=1;i<=tot;i++)if(!vis[i])dfs1(i);
for(i=tot;i;i--)if(vis[q[i]])dfs2(q[i],q[i]);
for(i=1;i<=n;i++)cnt[f[fin[i]]]++;
for(i=1;i<=tot;i++)if(cnt[i])ans+=1LL*cnt[i]*(cnt[i]-1)/2;
printf("%I64d\n",ans);
for(i=1;i<=n;i++)gt[i]=ga[i]=f[i]=0;
for(i=1;i<=tot;i++){
l[i]=r[i]=vis[i]=cnt[i]=0;
g[0][i]=g[1][i]=0;
}
ans=tot=edt=eda=ed=t=0;
}
return 0;
}

  

HDU5420 : Victor and Proposition的更多相关文章

  1. HDU 5420 Victor and Proposition

    Victor and Proposition Time Limit: 6000ms Memory Limit: 524288KB This problem will be judged on HDU. ...

  2. BestCoder Round #52 (div.1)

    这周六BC和CF又差点打架,精力不够啊...结果打BC没起来,就看了一眼题跑了...今天早上补补吧,(因为今天晚上还要打UER= =) 先放官方题解: 1000 Victor and Machine ...

  3. CF460D Little Victor and Set (找规律)

    D - Little Victor and Set Codeforces Round #262 (Div. 2) D D. Little Victor and Set time limit per t ...

  4. ACM: HDU 5418 Victor and World - Floyd算法+dp状态压缩

    HDU 5418 Victor and World Time Limit:2000MS     Memory Limit:131072KB     64bit IO Format:%I64d & ...

  5. HDU 5417 Victor and Machine

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5417 Problem Description Victor has a machine. When t ...

  6. Victor 串口 VCL 控件 - 简单实用, 功能强大的 C++ Builder 串口控件!

    源:Victor 串口 VCL 控件 - 简单实用, 功能强大的 C++ Builder 串口控件! 2014年02月06日发布控件的重要更新版本: Victor 串口控件 1.5.0.2 版本 (包 ...

  7. Victor and World(spfa+状态压缩dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/ ...

  8. Codeforces 460D Little Victor and Set(看题解)

    Little Victor and Set 其他都很好求, 只有k == 3的时候很难受.. 我们找到第一个不大于l的 t, 答案为 l, 3 * t, (3 * t) ^ l 感觉好像是对的, 感觉 ...

  9. 【HDU5421】Victor and String(回文树)

    [HDU5421]Victor and String(回文树) 题面 Vjudge 大意: 你需要支持以下操作: 动态在前端插入一个字符 动态在后端插入一个字符 回答当前本质不同的回文串个数 回答当前 ...

随机推荐

  1. jdk1.8源码Thread与Runnable区别

    一.概念 Thread实现了Runnable接口 public class Thread implements Runnable { /* Make sure registerNatives is t ...

  2. 【源码阅读】Mimikatz相关资料

    Mimikatz GitHub (源码) https://github.com/gentilkiwi/mimikatz Mimikatz GitHub Wiki (包含了一些说明文档) https:/ ...

  3. win7下iis中配置php.ini文件

    将php.ini-development配置文件重命名为php.ini配置文件即可. 接着做如下配置操作: 1.修改php.ini配置文件 打开php.ini配置文件,找到 12 ; On windo ...

  4. python文件操作及格式化输出

    1 文件与IO 1.1读写文本数据 读写各种不同的文本数据,如ASCII,UTF-8,UTF-9编码等. 使用带有rt模式的open()函数读取文本文件. 例如: with open('db', 'r ...

  5. 你会使用super()吗?你确定你了解它吗?

    我们经常在类的继承当中使用super(), 来调用父类中的方法.例如下面: class A: def func(self): print('OldBoy') class B(A): def func( ...

  6. Ubuntu 12.04 安装Tomcat7

    1.下载Tomcat7 打开Tomcat官网 http://tomcat.apache.org,在左边的导航栏的“Download"中找到Tomcat7.0目录,点击后进入Tomcat7的页 ...

  7. C# 各版本新特性

    C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...

  8. OPENCV SVM介绍和自带例子

    依据机器学习算法如何学习数据可分为3类:有监督学习:从有标签的数据学习,得到模型参数,对测试数据正确分类:无监督学习:没有标签,计算机自己寻找输入数据可能的模型:强化学习(reinforcement ...

  9. 【linux】crontab无效解决办法

    参考来源:http://www.tennfy.com/3088.html 问题: 我在crontab中添加了一条定时任务 * * * sh test.sh 出乎意料的是,该定时任务并没有执行.可是我直 ...

  10. JAVA 反射用法

    1.获得Class对象 Class<?>  classType  =  Class.forName() 可以通过传入一个全限定类名(包含包名)返回一个该类的Class类对象引用 . Cla ...