zoukankan      html  css  js  c++  java
  • 【POJ3237】Tree-树链剖分

    题目大意:有一棵树,每条边有边权,有两种操作:1.修改某条边的边权。2.将某两个点之间路径上所有边的边权修改成它的相反数。3.询问某两个点之间路径上的所有边的边权的最大值。对于每个询问,给出正确的答案。

    做法:一道比较难的树链剖分题,需要注意的是,在用线段树维护时,需要多维护一个区间最小值,因为在取反时,最大值和最小值会互换。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define inf 999999999
    using namespace std;
    int t,n,tot,f[10010],siz[10010],dep[10010],pos[10010],p,a,b,c;
    int d[10010][3],first[10010],son[10010],top[10010],root;
    int qpos[10010];
    char op[10];
    struct edge
    {
      int v,next;
    }e[20010];
    int seg[40010],m[40010],segp[40010]; //seg:区间最大值,m:区间最小值,segp:取反标记
    
    void readin(int a,int b,int c)
    {
      e[++tot].v=b;
      e[tot].next=first[a];
      first[a]=tot;
    }
    
    void dfs1(int now)
    {
      siz[now]=1;son[now]=0;
      for(int i=first[now];i>0;i=e[i].next)
        if (e[i].v!=f[now])
    	{
    	  dep[e[i].v]=dep[now]+1;
    	  f[e[i].v]=now;
    	  dfs1(e[i].v);
    	  siz[now]+=siz[e[i].v];
    	  if (siz[e[i].v]>siz[son[now]]) son[now]=e[i].v;
    	}
    }
    
    void dfs2(int now,int chain)
    {
      pos[now]=++p;top[now]=chain;
      if (son[now]) dfs2(son[now],chain);
      for(int i=first[now];i>0;i=e[i].next)
        if (e[i].v!=f[now]&&e[i].v!=son[now])
    	  dfs2(e[i].v,e[i].v);
    }
    
    void pushdown(int no)
    {
      if (segp[no]==-1)
      {
        int t;
    	t=seg[no<<1];seg[no<<1]=-m[no<<1];m[no<<1]=-t;
    	t=seg[(no<<1)+1];seg[(no<<1)+1]=-m[(no<<1)+1];m[(no<<1)+1]=-t;
    	segp[no]=1;
    	segp[no<<1]=-segp[no<<1];segp[(no<<1)+1]=-segp[(no<<1)+1];
      }
    }
    
    void pushup(int no)
    {
      seg[no]=max(seg[no<<1],seg[(no<<1)+1]);
      m[no]=min(m[no<<1],m[(no<<1)+1]);
    }
    
    void buildtree(int no,int l,int r)
    {
      int mid=(l+r)>>1;
      segp[no]=1;
      if (l==r) {seg[no]=d[qpos[l]][2];m[no]=seg[no];return;}
      buildtree(no<<1,l,mid);
      buildtree((no<<1)+1,mid+1,r);
      pushup(no);
    }
    
    void change(int no,int l,int r,int a,int c)
    {
      int mid=(l+r)>>1;
      if (l==r) {seg[no]=c;m[no]=c;return;}
      pushdown(no);
      if (a<=mid) change(no<<1,l,mid,a,c);
      else change((no<<1)+1,mid+1,r,a,c);
      pushup(no);
    }
    
    int querymx(int no,int l,int r,int s,int t)
    {
      int mid=(l+r)>>1;
      if (l>=s&&r<=t) return seg[no];
      int mx=-inf;
      pushdown(no);
      if (s<=mid) mx=max(mx,querymx(no<<1,l,mid,s,t));
      if (t>mid) mx=max(mx,querymx((no<<1)+1,mid+1,r,s,t));
      pushup(no);
      return mx;
    }
    
    void neg(int no,int l,int r,int s,int t)
    {
      int mid=(l+r)/2;
      if (l>=s&&r<=t)
      {
        segp[no]=-segp[no];
    	int tmp=seg[no];seg[no]=-m[no];m[no]=-tmp;
    	return;
      }
      pushdown(no);
      if (s<=mid) neg(no<<1,l,mid,s,t);
      if (t>mid) neg((no<<1)+1,mid+1,r,s,t);
      pushup(no);
    }
    
    int query(int a,int b)
    {
      int mx=-inf;
      while(top[a]!=top[b])
      {
        if (dep[top[a]]<dep[top[b]]) swap(a,b);
    	mx=max(mx,querymx(1,1,p,pos[top[a]],pos[a]));
    	a=f[top[a]];
      }
      if (dep[a]<dep[b]) swap(a,b);
      if (a!=b) mx=max(mx,querymx(1,1,p,pos[son[b]],pos[a]));
      return mx;
    }
    
    void nega(int a,int b)
    {
      while(top[a]!=top[b])
      {
        if (dep[top[a]]<dep[top[b]]) swap(a,b);
    	neg(1,1,p,pos[top[a]],pos[a]);
    	a=f[top[a]];
      }
      if (dep[a]<dep[b]) swap(a,b);
      if (a!=b) neg(1,1,p,pos[son[b]],pos[a]);
    }
    
    void read()
    {
      op[0]=' ';
      while (op[0]<'C'||op[0]>'Q') scanf("%s",op);
    }
    
    void input()
    {
      scanf("%d",&n);
      root=1;
      memset(first,0,sizeof(first));
      memset(seg,0,sizeof(seg));
      memset(m,0,sizeof(m));
      tot=f[root]=dep[root]=p=0;
      for(int i=1;i<=n-1;i++)
      {
        scanf("%d %d %d",&a,&b,&c);
    	d[i][0]=a;d[i][1]=b;d[i][2]=c;
    	readin(a,b,c);readin(b,a,c);
      }
      dfs1(root);
      dfs2(root,root);
      for(int i=1;i<n;i++)
      {
    	if (dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
    	qpos[pos[d[i][1]]]=i;
      }
      buildtree(1,1,p);
    }
    
    void work()
    {
      int a,b;
      for(read();op[0]!='D';read())
      {
        scanf("%d %d",&a,&b);
        if (op[0]=='Q') printf("%d
    ",query(a,b));
    	else if (op[0]=='C') change(1,1,p,pos[d[a][1]],b);
             else nega(a,b);
      }
    }
    
    int main()
    {
      for(scanf("%d",&t);t>0;t--)
      {
        input();
    	work();
      }
      
      return 0;
    }
    


  • 相关阅读:
    Web项目的WEB-INF目录使用说明以及重定向与转发
    HTTP中的重定向和请求转发的区别
    001杰信-创建MyEclipse与maven项目
    009Maven_建立私服——报错问题
    008Maven_建立私服
    007Maven_在Myeclipse创建web项目
    006Maven_在Myeclipse创建java项目
    005Maven_Myeclipse和Maven整合
    微服务架构下分布式事务方案
    推荐:Java性能优化系列集锦
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793961.html
Copyright © 2011-2022 走看看