標籤:樹狀數組 lock play open 題解 比較 src limit 電腦科學
【題意】
時間限制: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 31 22 32 44 54 61 31 55 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
【Hihocoder 1167】 高等理論電腦科學 (樹鏈的交,線段樹或樹狀數組維護區間和)