bzoj1103: [POI2007]大都市meg(树链剖分)

1103: [POI2007]大都市meg

题目:传送门 

简要题意:

   给你一棵树,给出每条边的权值,两个操作:1、询问根到编号x的最短路径的权值和  2、修改一条边的边权

 


 

题解:

   很明显啊,看懂了题基本上就A了

   一个树剖的板子啊...(其实不是最优解...卡时间过的嘿嘿)

 


代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 struct node
  8 {
  9     int x,y,next;
 10 }a[510000];int len,last[310000];
 11 void ins(int x,int y)
 12 {
 13     len++;a[len].x=x;a[len].y=y;
 14     a[len].next=last[x];last[x]=len;
 15 }
 16 struct trnode
 17 {
 18     int l,r,lc,rc,c;
 19 }tr[510000];int trlen;
 20 void bt(int l,int r)
 21 {
 22     int now=++trlen;
 23     tr[now].l=l;tr[now].r=r;tr[now].c=0;
 24     tr[now].lc=tr[now].rc=-1;
 25     if(l<r)
 26     {
 27         int mid=(l+r)/2;
 28         tr[now].lc=trlen+1;bt(l,mid);
 29         tr[now].rc=trlen+1;bt(mid+1,r);
 30     }
 31 }
 32 int fa[310000],dep[310000],son[310000],tot[310000];
 33 void pre_tree_node(int x)
 34 {
 35     tot[x]=1;son[x]=0;
 36     for(int k=last[x];k;k=a[k].next)
 37     {
 38         int y=a[k].y;
 39         if(y!=fa[x])
 40         {
 41             fa[y]=x;
 42             dep[y]=dep[x]+1;
 43             pre_tree_node(y);
 44             if(tot[y]>tot[son[x]])son[x]=y;
 45             tot[x]+=tot[y];
 46         }
 47     }
 48 }
 49 int z,ys[310000],top[310000];
 50 void pre_tree_edge(int x,int tp)
 51 {
 52     ys[x]=++z;top[x]=tp;
 53     if(son[x]!=0)pre_tree_edge(son[x],tp);
 54     for(int k=last[x];k;k=a[k].next)
 55     {
 56         int y=a[k].y;
 57         if(y!=fa[x] && y!=son[x])
 58             pre_tree_edge(y,y);
 59     }
 60 }
 61 void change(int now,int p,int c)
 62 {
 63     if(tr[now].l==tr[now].r){tr[now].c=c;return ;}
 64     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
 65     if(p<=mid)change(lc,p,c);
 66     else change(rc,p,c);
 67     tr[now].c=tr[lc].c+tr[rc].c;
 68 }
 69 int getsum(int now,int l,int r)
 70 {
 71     if(tr[now].l==l && tr[now].r==r)return tr[now].c;
 72     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
 73     if(r<=mid) return getsum(lc,l,r);
 74     else if(l>mid) return getsum(rc,l,r);
 75     else return getsum(lc,l,mid)+getsum(rc,mid+1,r);
 76 }
 77 int solve(int x,int y)
 78 {
 79     int tx=top[x],ty=top[y],ans=0;
 80     while(tx!=ty)
 81     {
 82         if(dep[tx]>dep[ty])
 83         {
 84             swap(x,y);
 85             swap(tx,ty);
 86         }
 87         ans+=getsum(1,ys[ty],ys[y]);
 88         y=fa[ty];ty=top[y];
 89     }
 90     if(x==y)return ans;
 91     else
 92     {
 93         if(dep[x]>dep[y])swap(x,y);
 94         return ans+getsum(1,ys[son[x]],ys[y]);
 95     }
 96 }
 97 struct edge
 98 {
 99     int x,y;
100 }e[310000];
101 int n;char st[5];
102 int main()
103 {
104     scanf("%d",&n);
105     for(int i=1;i<n;i++)
106     {
107         scanf("%d%d",&e[i].x,&e[i].y);
108         ins(e[i].x,e[i].y);
109         ins(e[i].y,e[i].x);
110     }
111     dep[1]=0;fa[1]=0;pre_tree_node(1);
112     z=0;pre_tree_edge(1,1);
113     trlen=0;bt(1,z);
114     int m;scanf("%d",&m);
115     for(int i=1;i<n;i++)
116     {
117         if(dep[e[i].x]>dep[e[i].y])swap(e[i].x,e[i].y);
118         change(1,ys[e[i].y],1);
119     }
120     for(int i=1;i<=n+m-1;i++)
121     {
122         scanf("%s",st+1);
123         if(st[1]=='A')
124         {
125             int x,y;
126             scanf("%d%d",&x,&y);
127             if(dep[x]>dep[y])swap(x,y);
128             change(1,ys[y],0);
129         }
130         else
131         {
132             int x;
133             scanf("%d",&x);
134             printf("%d\n",solve(1,x));
135         }
136     }
137     return 0;
138 }

 

posted @ 2018-03-10 08:12  CHerish_OI  阅读(207)  评论(0编辑  收藏  举报