您的位置:首页 > 理论基础

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

2016-11-10 18:12 447 查看
【题意】



时间限制: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐