zoukankan      html  css  js  c++  java
  • 【POJ2763】Housewife Wind-树链剖分

    题目大意:有一个村庄有n个小屋,小屋之间有道路,每条道路有通过所需的时间,从一个小屋有且只有一条路径到达另一个小屋(也就是一棵树)。有一个人一开始在s号小屋,下面有q个命令,命令分两种:1. 0 u:该人从当前小屋移动到u号小屋,并输出所需的时间。2. 1 i w:将输入的第i条道路的通过时间改为w。对于每个“0”命令,给出正确的答案。

    做法:树链剖分的模板题,用线段树维护边权即可。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,q,s,x,y,d,tot,op,first[100010],h[100010],t[100010],cost[100010];
    int f[100010],dep[100010],siz[100010],son[100010],top[100010],pos[100010];
    int fp[100010],to,j,w;
    long long seg[400010];
    struct {int v,next;} e[200010];
    
    void insert(int a,int b)
    {
      e[++tot].v=b;
      e[tot].next=first[a];
      first[a]=tot;
    }
    
    void dfs1(int v)
    {
      siz[v]=1;son[v]=0;
      for(int i=first[v];i;i=e[i].next)
        if (e[i].v!=f[v])
    	{
    	  dep[e[i].v]=dep[v]+1;
    	  f[e[i].v]=v;
    	  dfs1(e[i].v);
    	  siz[v]+=siz[e[i].v];
    	  if (siz[e[i].v]>siz[son[v]]) son[v]=e[i].v;
    	}
    }
    
    void dfs2(int v,int chain)
    {
      top[v]=chain;
      pos[v]=++tot;
      if (son[v]) dfs2(son[v],chain);
      for(int i=first[v];i;i=e[i].next)
        if (e[i].v!=f[v]&&e[i].v!=son[v])
    	  dfs2(e[i].v,e[i].v);
    }
    
    void buildtree(int no,int l,int r)
    {
      int mid=(l+r)>>1;
      if (l==r) seg[no]=cost[fp[l]];
      else
      {
        buildtree(no<<1,l,mid);
    	buildtree((no<<1)+1,mid+1,r);
    	seg[no]=seg[no<<1]+seg[(no<<1)+1];
      }
    }
    
    void change(int no,int l,int r,int p,int w)
    {
      int mid=(l+r)>>1;
      if (l==r) seg[no]=w;
      else
      {
        if (p<=mid) change(no<<1,l,mid,p,w);
    	else change((no<<1)+1,mid+1,r,p,w);
    	seg[no]=seg[no<<1]+seg[(no<<1)+1];
      }
    }
    
    long long querysum(int no,int l,int r,int s,int t)
    {
      int mid=(l+r)>>1;
      if (l>=s&&r<=t) return seg[no];
      else
      {
        long long sum=0;
        if (s<=mid) sum+=querysum(no<<1,l,mid,s,t);
    	if (t>mid) sum+=querysum((no<<1)+1,mid+1,r,s,t);
    	return sum;
      }
    }
    
    long long query(int a,int b)
    {
      long long ans=0;
      while(top[a]!=top[b])
      {
        if (dep[top[a]]<dep[top[b]]) swap(a,b);
    	ans+=querysum(1,1,n,pos[top[a]],pos[a]);
    	a=f[top[a]];
      }
      if (dep[a]>dep[b]) swap(a,b);
      if (a!=b) ans+=querysum(1,1,n,pos[son[a]],pos[b]);
      return ans;
    }
    
    int main()
    {
      scanf("%d%d%d",&n,&q,&s);
      
      memset(first,0,sizeof(first));
      f[1]=dep[1]=siz[0]=tot=0;
      for(int i=1;i<n;i++)
      {
        scanf("%d%d%d",&h[i],&t[i],&cost[i]);
    	insert(h[i],t[i]);insert(t[i],h[i]);
      }
      
      dfs1(1);tot=0;
      dfs2(1,1);
      for(int i=1;i<n;i++)
      {
        if (dep[h[i]]<dep[t[i]]) swap(h[i],t[i]);
    	fp[pos[h[i]]]=i;
      }
      buildtree(1,1,n);
      
      for(int i=1;i<=q;i++)
      {
        scanf("%d",&op);
    	if (op==0)
    	{
    	  scanf("%d",&to);
    	  printf("%lld
    ",query(s,to));
    	  s=to;
        }
    	else
    	{
    	  scanf("%d%d",&j,&w);
    	  change(1,1,n,pos[h[j]],w);
    	}
      }
      
      return 0;
    }
    


  • 相关阅读:
    macbook 无声音解决方案
    webapck dev server代理请求 json截断问题
    百度卫星地图开启
    服务器 nginx配置 防止其他域名绑定自己的服务器
    记一次nginx php配置的心路历程
    遇到npm报错read ECONNRESET怎么办
    运行svn tortoiseSvn cleanup 命令失败的解决办法
    svn add 命令 递归目录下所有文件
    m4出现Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
    Ubuntu下安装GCC,mpc、mpfr、gmp
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793965.html
Copyright © 2011-2022 走看看