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;
    }
    


  • 相关阅读:
    背水一战 Windows 10 (26)
    背水一战 Windows 10 (25)
    背水一战 Windows 10 (24)
    背水一战 Windows 10 (23)
    背水一战 Windows 10 (22)
    背水一战 Windows 10 (21)
    背水一战 Windows 10 (20)
    背水一战 Windows 10 (19)
    背水一战 Windows 10 (18)
    背水一战 Windows 10 (17)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793965.html
Copyright © 2011-2022 走看看