【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)

【题意】

时间限制:20000ms
单点时限:1000ms
内存限制:256MB

描述

少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦。所以她出去晃了一晃,做起了一些没什么意义的事情来放松自己。
门前有一颗n个节点树,幽香发现这个树上有n个小精灵。然而这些小精灵都比较害羞,只会在一条特定的路径上活动。第i个小精灵会在ai到bi的路径上活动。
两个小精灵是朋友,当且仅当它们的路径是有公共点的。
于是幽香想要知道,有多少对小精灵a和b,a和b是朋友呢?其中a不等于b,a,b和b,a看做一对。

输入

第一行n和P (1 <= n, P <=100000),表示树的大小和小精灵的个数。树的节点从1到n标号。
接下来n-1行,每行两个数a,b,表示a到b之间有一条边。
接下来P行,第i行两个数ai,bi,表示小精灵i的活动范围是ai到bi,其中ai不等于bi。

输出

一行答案,表示对数。

样例输入
6 3
1 2
2 3
2 4
4 5
4 6
1 3
1 5
5 6
样例输出
2

 

【分析】

   ORZ 。。。

   我好蠢。。一直想树剖以及线段的交。。。【并且不是线段

  大神题解here:

  两条树链相交,当且仅当一条树链的lca在另一条树链上,对于每个树链,统计有多少个树链的lca在被他包含,有时两条树链互相满足这个条件,但仅仅当这两条树链的lca相等时才会有,所以特判一下


  上面说得很清楚了,区间的和维护用树状数组就可以了。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 #define Maxn 100010
  9 #define LL long long
 10 
 11 struct node
 12 {
 13     int x,y,next;
 14 }t[Maxn*2];int len;
 15 
 16 int first[Maxn],px[Maxn],py[Maxn];
 17 
 18 void ins(int x,int y)
 19 {
 20     t[++len].x=x;t[len].y=y;
 21     t[len].next=first[x];first[x]=len;
 22 }
 23 
 24 int son[Maxn],dfn[Maxn],sm[Maxn],dep[Maxn],fa[Maxn];
 25 void dfs1(int x,int f)
 26 {
 27     sm[x]=1;son[x]=0;dep[x]=dep[f]+1;fa[x]=f;
 28     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
 29     {
 30         int y=t[i].y;
 31         dfs1(y,x);
 32         sm[x]+=sm[y];
 33         if(sm[y]>sm[son[x]]) son[x]=y;
 34     }
 35 }
 36 
 37 int tp[Maxn],cnt;
 38 void dfs2(int x,int f,int tpp)
 39 {
 40     dfn[x]=++cnt;tp[x]=tpp;
 41     if(son[x]) dfs2(son[x],x,tpp);
 42     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&t[i].y!=son[x])
 43      dfs2(t[i].y,x,t[i].y);
 44 }
 45 
 46 int c[Maxn],n;
 47 bool lca[Maxn];
 48 
 49 void add(int x,int y)
 50 {
 51     for(int i=x;i<=n;i+=i&(-i))
 52         c[i]+=y;
 53 }
 54 
 55 int query(int l,int r)
 56 {
 57     int ans=0;
 58     for(int i=r;i>=1;i-=i&(-i))
 59         ans+=c[i];
 60     l--;
 61     for(int i=l;i>=1;i-=i&(-i))
 62         ans-=c[i];
 63     return ans;
 64 }
 65 
 66 int gans(int x,int y,int p)
 67 {
 68     int ans=0,tt;
 69     while(tp[x]!=tp[y])
 70     {
 71         if(dep[tp[x]]<dep[tp[y]]) tt=x,x=y,y=tt;
 72         if(p==1) ans+=query(dfn[tp[x]],dfn[x]);
 73         x=fa[tp[x]];
 74     }
 75     if(dep[x]<dep[y]) tt=x,x=y,y=tt;
 76     if(p==1)
 77     {
 78         ans+=query(dfn[y],dfn[x]);
 79         return ans;
 80     }
 81     else return y;
 82 }
 83 
 84 int main()    
 85 {
 86     int p;
 87     LL ans=0;
 88     scanf("%d%d",&n,&p);
 89     len=0;
 90     memset(first,0,sizeof(first));
 91     for(int i=1;i<n;i++)
 92     {
 93         int x,y;
 94         scanf("%d%d",&x,&y);
 95         ins(x,y);ins(y,x);
 96     }
 97     for(int i=1;i<=p;i++) scanf("%d%d",&px[i],&py[i]);
 98     sm[0]=0;dep[0]=0;
 99     dfs1(1,0);cnt=0;
100     dfs2(1,0,1);
101     memset(c,0,sizeof(c));
102     memset(lca,0,sizeof(lca));
103     for(int i=1;i<=p;i++)
104     {
105         int x=gans(px[i],py[i],0);
106         lca[x]=1;
107         add(dfn[x],1);
108     }
109     for(int i=1;i<=p;i++)
110     {
111         int x=gans(px[i],py[i],1);
112         ans+=x;
113     }
114     for(int i=1;i<=n;i++) if(lca[i])
115     {
116         int x=query(dfn[i],dfn[i]);
117         ans-=x*(x-1)/2+x;
118     }
119     printf("%lld\n",ans);
120     return 0;
121 }
View Code

 

 

2016-11-10 18:17:12

 

posted @ 2016-11-10 18:12  konjak魔芋  阅读(818)  评论(0编辑  收藏  举报