【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 }
2016-11-10 18:17:12