• poj 2763 Housewife Wind (树链剖分)


    题目链接:http://poj.org/problem?id=2763

    题意:

    给定一棵含n个结点的树和树的边权,共有q次操作,分为两种

    0 c :求从位置s到c的距离,然后s变成c

    1 a b:把第a条边的权值变为b

    分析:

    树链剖分,注意查询后要改变起点

    代码如下:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int maxn=110000;
      8 
      9 struct Edge
     10 {
     11     int to,next;
     12 }edge[maxn*2];
     13 int head[maxn];
     14 int cnt,tmp,n;
     15 int dep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn],rank[maxn];
     16 struct Node
     17 {
     18     int u,v,c;
     19 }node[maxn];
     20 
     21 void init()
     22 {
     23     memset(head,-1,sizeof(head));
     24     memset(son,-1,sizeof(son));
     25     tmp=0;
     26     cnt=0;
     27 }
     28 
     29 void addedge(int u,int v)
     30 {
     31     edge[cnt].to=v;
     32     edge[cnt].next=head[u];
     33     head[u]=cnt++;
     34 }
     35 
     36 void dfs_1(int u,int f,int d)
     37 {
     38     dep[u]=d;
     39     size[u]=1;
     40     fa[u]=f;
     41     for(int i=head[u];i!=-1;i=edge[i].next)
     42     {
     43         int v=edge[i].to;
     44         if(v==f)
     45             continue;
     46         dfs_1(v,u,d+1);
     47         size[u]+=size[v];
     48         if(son[u]==-1||size[son[u]]<size[v])
     49             son[u]=v;
     50     }
     51 }
     52 
     53 void dfs_2(int u,int tp)
     54 {
     55     top[u]=tp;
     56     id[u]=++tmp;
     57     rank[tmp]=u;
     58     if(son[u]!=-1)
     59         dfs_2(son[u],tp);
     60     for(int i=head[u];i!=-1;i=edge[i].next)
     61     {
     62         int v=edge[i].to;
     63         if(v!=fa[u]&&v!=son[u])
     64             dfs_2(v,v);
     65     }
     66 }
     67 struct Tree
     68 {
     69     int left,right;
     70     int t;
     71 }tree[maxn*4];
     72 
     73 void pushup(int i)
     74 {
     75     tree[i].t=tree[i*2].t+tree[i*2+1].t;
     76 }
     77 
     78 void build(int i,int begin,int end)
     79 {
     80     tree[i].left=begin;
     81     tree[i].right=end;
     82     tree[i].t=0;
     83     if(begin==end)
     84         return;
     85     int mid=(begin+end)/2;
     86     build(i*2,begin,mid);
     87     build(i*2+1,mid+1,end);
     88 }
     89 
     90 void update(int i,int k,int val)
     91 {
     92     if(tree[i].left==k&&tree[i].right==k)
     93     {
     94         tree[i].t=val;
     95         return;
     96     }
     97     int mid=(tree[i].left+tree[i].right)/2;
     98     if(k<=mid)
     99         update(i*2,k,val);
    100     else
    101         update(i*2+1,k,val);
    102     pushup(i);
    103 }
    104 
    105 int query(int i,int begin,int end)
    106 {
    107     if(tree[i].left>=begin&&tree[i].right<=end)
    108         return tree[i].t;
    109     int mid=(tree[i].left+tree[i].right)/2;
    110     int res=0;
    111     if(mid>=begin)
    112         res+=query(i*2,begin,end);
    113     if(mid<end)
    114         res+=query(i*2+1,begin,end);
    115     return res;
    116 }
    117 
    118 int find(int u,int v)
    119 {
    120     int tp1=top[u],tp2=top[v];
    121     int res=0;
    122     while(tp1!=tp2)
    123     {
    124         if(dep[tp1]<dep[tp2])
    125         {
    126             swap(tp1,tp2);
    127             swap(u,v);
    128         }
    129         res+=query(1,id[tp1],id[u]);
    130         u=fa[tp1];
    131         tp1=top[u];
    132     }
    133     if(u==v)
    134         return res;
    135     if(dep[u]>dep[v])
    136         swap(u,v);
    137     res+=query(1,id[son[u]],id[v]);
    138     return res;
    139 }
    140 
    141 int main()
    142 {
    143     int n,q,s;
    144     scanf("%d%d%d",&n,&q,&s);
    145     init();
    146     for(int i=1;i<n;i++)
    147     {
    148         scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].c);
    149         addedge(node[i].u,node[i].v);
    150         addedge(node[i].v,node[i].u);
    151     }
    152     dfs_1(1,0,1);
    153     dfs_2(1,1);
    154     build(1,1,tmp);
    155     for(int i=1;i<n;i++)
    156     {
    157         if(dep[node[i].u]>dep[node[i].v])
    158             swap(node[i].u,node[i].v);
    159         update(1,id[node[i].v],node[i].c);
    160     }
    161     for(int i=0;i<q;i++)
    162     {
    163         int a,k,w;
    164         scanf("%d",&a);
    165         if(a==0)
    166         {
    167             scanf("%d",&k);
    168             printf("%d
    ",find(s,k));
    169             s=k;
    170         }
    171         else
    172         {
    173             scanf("%d%d",&k,&w);
    174             update(1,id[node[k].v],w);
    175         }
    176     }
    177     return 0;
    178 }
  • 相关阅读:
    记一次阿里云硬盘在线扩容
    大文件传输技巧-----split切割
    数据库迁移-------通过ibdata1文件和数据库文件迁移
    小技巧---------------vim 使用技巧 set paste 解决粘贴乱序问题
    webfrom 做项目的注意事项
    webform 复合控件
    wenfrom的简单控件和repeater控件
    分页功能 与 分类查询功能合并
    内置对象2
    简单的人员管理系统
  • 原文地址:https://www.cnblogs.com/yaoyueduzhen/p/5311230.html
Copyright © 2020-2023  润新知