bzoj 3772 精神汙染 主席樹+dfs序
阿新 • • 發佈:2017-12-21
mit cst names root sin val input 存在 覆蓋
Submit: 637 Solved: 177
[Submit][Status][Discuss]
1 2
2 3
3 4
2 5
3 5
2 5
1 4
樣例解釋
可以選擇的路徑對有(1,2),(1,3),(2,3),只有路徑1完全覆蓋路徑2。
將每個詢問的點,按照dfs序的順序,建立主席樹
每棵線段樹的版本是其祖先的版本加上詢問中在其節點上的,
比如詢問是x,y,那麽建樹在建到x的時候,將y加入當前線段樹
在y的in中加1,out中減1,in表示進入的dfs序,out表示出來的dfs序
這個有什麽用呢。
對於詢問x,y,f表示其lca,就是詢問x和y的樹中
精神汙染
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 637 Solved: 177
[Submit][Status][Discuss]
Description
兵庫縣位於日本列島的中央位置,北臨日本海,南面瀨戶內海直通太平洋,中央部位是森林和山地,與擁有關西機場的大阪府比鄰而居,是關西地區面積最大的縣,是集經濟和文化於一體的一大地區,是日本西部門戶,海陸空交通設施發達。瀨戶內海沿岸氣候溫暖,多晴天,有日本少見的貿易良港神戶港所在的神戶市和曾是豪族城邑“城下町”的姬路市等大城市,還有以療養地而聞名的六甲山地等。 兵庫縣官方也大力發展旅遊,為了方便,他們在縣內的N個旅遊景點上建立了n-1條觀光道,構成了一棵圖論中的樹。同時他們推出了M條觀光線路,每條線路由兩個節點x和y指定,經過的旅遊景點就是樹上x到y的唯一路徑上的點。保證一條路徑只出現一次。 你和你的朋友打算前往兵庫縣旅遊,但旅行社還沒有告知你們最終選擇的觀光線路是哪一條(假設是線路A)。這時候你得到了一個消息:在兵庫北有一群喪心病狂的香菜蜜,他們已經選定了一條觀光線路(假設是線路B),對這條路線上的所有景點都釋放了【精神汙染】。這個計劃還有可能影響其他的線路,比如有四個景點1-2-3-4,而【精神汙染】的路徑是1-4,那麽1-3,2-4,1-2等路徑也被視為被完全汙染了。 現在你想知道的是,假設隨便選擇兩條不同的路徑A和B,存在一條路徑使得如果這條路徑被汙染,另一條路徑也被汙染的概率。換句話說,一條路徑被另一條路徑包含的概率。
Input
第一行兩個整數N,M 接下來N-1行,每行兩個數a,b,表示A和B之間有一條觀光道。 接下來M行,每行兩個數x,y,表示一條旅遊線路。
Output
所求的概率,以最簡分數形式輸出。
Sample Input
5 31 2
2 3
3 4
2 5
3 5
2 5
1 4
Sample Output
1/3樣例解釋
可以選擇的路徑對有(1,2),(1,3),(2,3),只有路徑1完全覆蓋路徑2。
HINT
100%的數據滿足:N,M<=100000 題解:
比如統計兩個紅點的答案,分別為x,y,f為lca,
所以答案+x,y,f,fa[f]上詢問in[f],in[x]
+x,y,f,fa[f]上詢問in[f],in[y]
-x,y,f,fa[f]上詢問in[f],in[f]
-1減去自己
即可。
題目給的是沒有相同的路徑的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<set> 5 #include<vector> 6 #include<algorithm> 7 #include<cmath> 8 9 #define ll long long 10 #define N 100007 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(ch>‘9‘||ch<‘0‘){if (ch==‘-‘) f=-1;ch=getchar();} 16 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} 17 return x*f; 18 } 19 20 int n,m,ind,sz; 21 ll fz,fm; 22 int ls[N*40],rs[N*41],sum[N*40]; 23 int deep[N],root[N*2],in[N],out[N]; 24 int fa[N][17],ci[20]; 25 vector<int>a[N]; 26 int cnt,hed[N],nxt[N*2],rea[N*2]; 27 struct query 28 { 29 int x,y; 30 }q[N]; 31 bool operator<(query a,query b) 32 { 33 if(a.x==b.x)return a.y<b.y; 34 else return a.x<b.x; 35 } 36 37 ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);} 38 void add(int u,int v) 39 { 40 nxt[++cnt]=hed[u]; 41 hed[u]=cnt; 42 rea[cnt]=v; 43 } 44 void dfs(int x) 45 { 46 for(int i=1;(1<<i)<=deep[x];i++) 47 fa[x][i]=fa[fa[x][i-1]][i-1]; 48 in[x]=++ind; 49 for(int i=hed[x];i!=-1;i=nxt[i]) 50 { 51 int v=rea[i]; 52 if(v!=fa[x][0]) 53 { 54 fa[v][0]=x; 55 deep[v]=deep[x]+1; 56 dfs(v); 57 } 58 } 59 out[x]=++ind; 60 } 61 inline void update(int p){sum[p]=sum[ls[p]]+sum[rs[p]];} 62 /*void ins(int yl,int &xz,int l,int r,int pos,int val) 63 { 64 xz=++sz,ls[xz]=ls[yl],rs[xz]=rs[yl]; 65 if(l==r) 66 { 67 sum[xz]=sum[yl]+val; 68 return; 69 } 70 int mid=(l+r)>>1; 71 if(pos<=mid) ins(ls[yl],ls[xz],l,mid,pos,val); 72 else ins(rs[yl],rs[xz],mid+1,r,pos,val); 73 update(xz); 74 }*/ 75 76 int insert(int x,int l,int r,int pos,int val) 77 { 78 int t=++sz; 79 ls[t]=ls[x];rs[t]=rs[x]; 80 if(l==r){sum[t]=sum[x]+val;return t;} 81 int mid=(l+r)>>1; 82 if(pos<=mid)ls[t]=insert(ls[t],l,mid,pos,val); 83 else rs[t]=insert(rs[t],mid+1,r,pos,val); 84 sum[t]=sum[ls[t]]+sum[rs[t]]; 85 return t; 86 } 87 int query(int p1,int p2,int p3,int p4,int l,int r,int st,int ed) 88 { 89 int mid=(l+r)>>1; 90 if(l==st&&r==ed) {return sum[p1]+sum[p2]-sum[p3]-sum[p4];} 91 if(ed<=mid) return query(ls[p1],ls[p2],ls[p3],ls[p4],l,mid,st,ed); 92 else if(st>mid) return query(rs[p1],rs[p2],rs[p3],rs[p4],mid+1,r,st,ed); 93 else return query(ls[p1],ls[p2],ls[p3],ls[p4],l,mid,st,mid)+query(rs[p1],rs[p2],rs[p3],rs[p4],mid+1,r,mid+1,ed); 94 } 95 /* 96 void build(int x) 97 { 98 root[0]=root[fa[x][0]]; 99 for(int i=0;i<a[x].size();i++) 100 { 101 ins(root[0],root[N-1],1,ind,in[a[x][i]],1); 102 ins(root[N-1],root[x],1,ind,out[a[x][i]],-1); 103 } 104 for(int i=hed[x];i!=-1;i=nxt[i]) 105 { 106 int v=rea[i]; 107 if(v!=fa[x][0]) build(v); 108 } 109 }*/ 110 111 void build(int x) 112 { 113 root[x]=root[fa[x][0]]; 114 for(int i=0;i<a[x].size();i++) 115 { 116 root[x]=insert(root[x],1,ind,in[a[x][i]],1); 117 root[x]=insert(root[x],1,ind,out[a[x][i]],-1); 118 } 119 for(int i=hed[x];i!=-1;i=nxt[i]) 120 { 121 int v=rea[i]; 122 if(v!=fa[x][0]) 123 build(v); 124 } 125 } 126 int lca(int a,int b) 127 { 128 if (deep[a]<deep[b]) swap(a,b); 129 int i;for (i=0;(1<<i)<=deep[a];i++);i--; 130 for (int j=i;j>=0;j--) 131 if (deep[a]-(1<<j)>=deep[b]) a=fa[a][j]; 132 if (a==b) return a; 133 for (int j=i;j>=0;j--) 134 if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j]; 135 return fa[a][0]; 136 } 137 void solve() 138 { 139 for(int i=1;i<=m;i++) 140 { 141 int x=q[i].x,y=q[i].y,f=lca(x,y); 142 fz+=query(root[x],root[y],root[f],root[fa[f][0]],1,ind,in[f],in[x]); 143 fz+=query(root[x],root[y],root[f],root[fa[f][0]],1,ind,in[f],in[y]); 144 fz-=query(root[x],root[y],root[f],root[fa[f][0]],1,ind,in[f],in[f]); 145 fz--; 146 } 147 } 148 inline void init() 149 { 150 ci[0]=1; 151 for(int i=1;i<20;i++)ci[i]=ci[i-1]<<1; 152 153 memset(hed,-1,sizeof(hed)); 154 n=read();m=read(); 155 for(int i=1;i<n;i++) 156 { 157 int u=read(),v=read(); 158 add(u,v),add(v,u);//加邊,沒什麽問題。 159 } 160 for(int i=1;i<=m;i++) 161 { 162 int x=read(),y=read(); 163 a[x].push_back(y);//在邊的起點放入另外一個端點。 164 q[i].x=x,q[i].y=y; 165 } 166 sort(q+1,q+m+1);//q按照x為第一關鍵字來排序。 167 } 168 int main() 169 { 170 freopen("fzy.in","r",stdin); 171 freopen("fzy.out","w",stdout); 172 173 init(),dfs(1),build(1),solve(); 174 175 fm=(ll)m*(m-1)/2; 176 ll t=gcd(fz,fm); 177 fz/=t;fm/=t; 178 printf("%lld/%lld",fz,fm); 179 }
bzoj 3772 精神汙染 主席樹+dfs序