zoukankan      html  css  js  c++  java
  • 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
    ",solve(1,x));
    135         }
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    C++之private虚函数
    图的遍历DFS与BFS(邻接表)
    拓扑排序(邻接矩阵)
    paypal Encryption 支付编程全解
    JAVA 正则表达式 分组
    正则表达式 <A HREF>
    Linux 逻辑卷管理 实例
    LINUX命令笔记(2)
    哀悼日:快速设置黑白页面
    XEN笔记
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8537299.html
Copyright © 2011-2022 走看看