题解CF191C Fools and Roads

题面:CF191C Fools and Roads

树上差分模板题吧。唯一需要注意的也是值得讲的就是:边化点。

对于(i,j)连接的边,我们记录这条边的方式就是把(i,j)中深度大的点的id作为这条边的编号,第二遍dfs统计的时候可以直接记下来。

提一下树上差分:

边上操作:++s[u],++s[v],s[lca(u,v)]-=2;

点上操作:++s[u],++s[v],--s[lca(u,v)],--s[fa[lca(u,v)]];

 1 #include<cstdio>
 2 #define it register int
 3 #define il inline
 4 const int N=500005;
 5 int u,v,h[N],nxt[N],adj[N],t,n,fa[N][20],d[N],lc,uu[N],vv[N],s[N],id[N],m,ans[N];
 6 il void add(){
 7     nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u;
 8 }
 9 il void dfs(it x){
10     d[x]=d[fa[x][0]]+1;
11     for(it i=h[x];i;i=nxt[i])
12         if(adj[i]!=fa[x][0])
13             fa[adj[i]][0]=x,dfs(adj[i]);
14 }
15 il void DFS(it x){
16     for(it i=h[x];i;i=nxt[i])
17         if(adj[i]!=fa[x][0])
18             DFS(adj[i]),s[x]+=s[adj[i]];
19     ans[id[x]]=s[x];
20 }
21 il void sp(int &p,int &q){
22     p+=q,q=p-q,p-=q;
23 }
24 il void lca(it p,it q){
25     if(d[p]<d[q]) sp(p,q);
26     it ds=d[p]-d[q];
27     for(it i=17;i>=0;--i)
28         if(ds&(1<<i)) p=fa[p][i];
29     if(p==q){lc=p;return;}
30     for(it i=17;i>=0;--i)
31         if(fa[p][i]!=fa[q][i])
32             p=fa[p][i],q=fa[q][i];
33     lc=fa[p][0];
34 }
35 il void fr(int &num){
36     num=0;char c=getchar();int p=1;
37     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
38     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
39     num*=p;
40 }
41 int main(){
42     fr(n);
43     for(it i=1;i<n;++i) fr(u),fr(v),add(),uu[i]=u,vv[i]=v;
44     dfs(1);
45     for(it i=1;i<n;++i) d[uu[i]]>d[vv[i]]?id[uu[i]]=i:id[vv[i]]=i;
46     fr(m);
47     for(it j=1;j<=17;++j)
48         for(it i=1;i<=n;++i)
49             fa[i][j]=fa[fa[i][j-1]][j-1];
50     while(m--)
51         fr(u),fr(v),++s[u],++s[v],lca(u,v),s[lc]-=2; 
52     DFS(1);
53     for(it i=1;i<n;++i) printf("%d ",ans[i]); 
54     return 0;
55 }
View Code

 

posted @ 2019-10-05 20:47  kylin_xy  阅读(148)  评论(0编辑  收藏  举报