zoukankan      html  css  js  c++  java
  • [POJ3237]树的维护

    P1424 - [POJ3237]树的维护

    Description

    给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
    CHANGE i v:将第i条边的权值改成v。
    NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
    QUERY a b:找出点a到点b路径上各边的最大权值。

    Input

    第一行有一个整数N(N<=10000)。
    接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。
    接下来是若干条指令(不超过10^5条),都按照上面所说的格式。
    最后一行是"DONE".

    Output

    对每个“QUERY”指令,输出一行,即路径上各边的最大权值。

    Sample Input

    3
    1 2 1
    2 3 2
    QUERY 1 2
    CHANGE 1 3
    QUERY 1 2
    DONE

    Sample Output

    1
    3

    树链剖分,在线段树中维护一个区间最大和区间最小,
    在进行取反操作时,将区间最小的相反数赋给最大,将区间最大值的相反数赋给最小,并标记
    lazy数组。
    另外,根节点在线段树中的值为0,但这不需要管,因为不会查询到根节点。

      1 #include<set>
      2 #include<map>
      3 #include<queue>
      4 #include<stack>
      5 #include<ctime>
      6 #include<cmath>
      7 #include<string>
      8 #include<vector>
      9 #include<cstdio>
     10 #include<cstdlib>
     11 #include<cstring>
     12 #include<iostream>
     13 #include<algorithm>
     14 #define maxn 10010
     15 #define ls o*2
     16 #define rs o*2+1
     17 #define mi int mid=(l+r)>>1
     18 using namespace std;
     19 struct data{
     20   int nex,to,w;
     21 }e[maxn*2];
     22 char s[10];
     23 int head[maxn],edge=0,n;
     24 int top[maxn],dis[maxn],dad[maxn],son[maxn],size[maxn],dfn[maxn],dfp[maxn],deep[maxn];
     25 int b[maxn*4],b1[maxn*4],lazy[maxn*4];
     26 void dfs1(int x,int fa){
     27   size[x]++;
     28   for(int i=head[x];i;i=e[i].nex){
     29     int u=e[i].to;
     30     if(u==fa) continue;
     31     dad[u]=x;
     32     dis[u]=e[i].w;
     33     deep[u]=deep[x]+1;
     34     dfs1(u,x);
     35     size[x]+=size[u];
     36     if(size[u]>size[son[x]]) son[x]=u;
     37   }
     38 }
     39 int de=0;
     40 void dfs2(int x,int fa){
     41   ++de;
     42   dfn[x]=de;dfp[de]=x;
     43   if(son[x]!=0) top[son[x]]=top[x],dfs2(son[x],x);
     44   for(int i=head[x];i;i=e[i].nex){
     45     int v=e[i].to;
     46     if(v==fa || v==son[x]) continue;
     47     top[v]=v;
     48     dfs2(v,x);
     49   }
     50 }
     51 void add(int from,int to,int w){
     52   e[++edge].nex=head[from];
     53   e[edge].to=to;
     54   e[edge].w=w;
     55   head[from]=edge;
     56 }
     57 void build(int o,int l,int r){
     58   if(l==r){b[o]=dis[dfp[l]];b1[o]=dis[dfp[l]];return;}
     59   mi;
     60   build(ls,l,mid);build(rs,mid+1,r);
     61   b[o]=min(b[ls],b[rs]);
     62   b1[o]=max(b1[ls],b1[rs]);
     63 }
     64 void down(int o){
     65   if(lazy[o]==-1){
     66     int tmp=b[ls];
     67     b[ls]=-b1[ls];b1[ls]=-tmp;
     68   }
     69   if(lazy[o]==-1){
     70     int tmp=b[rs];
     71     b[rs]=-b1[rs];b1[rs]=-tmp;
     72   }
     73   lazy[ls]*=lazy[o],lazy[rs]*=lazy[o];
     74   lazy[o]=1;
     75 }
     76 int query(int o,int l,int r,int u,int v){
     77   if(l!=r)down(o);
     78   if(l>=u && r<=v) return b1[o];
     79   if(l>v || r<u) return -1999999999;
     80   mi;
     81   if(v<=mid) return query(ls,l,mid,u,v);
     82   else if(u>mid) return query(rs,mid+1,r,u,v);
     83   else return max(query(ls,l,mid,u,mid),query(rs,mid+1,r,mid+1,v));
     84 }
     85 int lca(int x,int y){
     86   int ans=-1999999999;
     87   while(top[x]!=top[y]){
     88     if(deep[top[x]]>deep[top[y]]) ans=max(ans,query(1,1,n,dfn[top[x]],dfn[x])),x=dad[top[x]]; 
     89     else ans=max(ans,query(1,1,n,dfn[top[y]],dfn[y])),y=dad[top[y]];
     90   }
     91   if(deep[x]>deep[y]) swap(x,y);
     92   if(x!=y)
     93     ans=max(ans,query(1,1,n,dfn[x]+1,dfn[y]));
     94   return ans;
     95 }
     96 void negatee(int o,int l,int r,int u,int v){
     97   if(l!=r)down(o);
     98   if(l>=u && r<=v){
     99     int tmp=b[o];
    100     b[o]=-b1[o];b1[o]=-tmp;
    101     lazy[o]*=-1;
    102     return;
    103   }
    104   mi;
    105   if(v<=mid) negatee(ls,l,mid,u,v);
    106   else if(u>mid) negatee(rs,mid+1,r,u,v);
    107   else negatee(ls,l,mid,u,mid),negatee(rs,mid+1,r,mid+1,v);
    108   b[o]=min(b[ls],b[rs]);
    109   b1[o]=max(b1[ls],b1[rs]);
    110 }
    111 void lca1(int x,int y){
    112   while(top[x]!=top[y]){
    113     if(deep[top[x]]>deep[top[y]]) negatee(1,1,n,dfn[top[x]],dfn[x]),x=dad[top[x]];
    114     else negatee(1,1,n,dfn[top[y]],dfn[y]),y=dad[top[y]];
    115   }
    116   if(deep[x]>deep[y]) swap(x,y);
    117   if(x!=y)
    118     negatee(1,1,n,dfn[x]+1,dfn[y]);
    119 }
    120 void change(int o,int l,int r,int k,int p){
    121   if(l!=r) down(o);
    122   if(l==r){b[o]=p,b1[o]=p;return;}
    123   mi;
    124   if(k<=mid)change(ls,l,mid,k,p);
    125   else change(rs,mid+1,r,k,p);
    126   b[o]=min(b[ls],b[rs]);
    127   b1[o]=max(b1[ls],b1[rs]);
    128 }
    129 int main()
    130 {
    131   freopen("!.in","r",stdin);
    132   freopen("!.out","w",stdout);
    133   scanf("%d",&n);int x,y,z;
    134   for(int i=1;i<=4*n;i++) lazy[i]=1;
    135   for(int i=1;i<n;i++)
    136     scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    137   top[1]=1,dad[1]=1;
    138   dfs1(1,0);dfs2(1,0);build(1,1,n);
    139   while(1){
    140     scanf("%s",s);
    141     if(s[0]=='D') break;
    142     if(s[0]=='Q'){
    143       int x,y;
    144       scanf("%d%d",&x,&y);
    145       printf("%d
    ",lca(x,y));
    146     }
    147     if(s[0]=='C'){
    148       int x,y;scanf("%d%d",&x,&y);
    149       int k1=e[2*x-1].to,k2=e[2*x].to;
    150       int k;
    151       if(deep[k1]>deep[k2]) k=k1;
    152       else k=k2;
    153       change(1,1,n,dfn[k],y);
    154     }
    155     if(s[0]=='N'){
    156       int x,y;
    157       scanf("%d%d",&x,&y);
    158       lca1(x,y);
    159     }
    160   }
    161   return 0;
    162 }
    
    
    
     
  • 相关阅读:
    Hadoop第一天
    Python第二天-字典类型的基本使用讲解
    Python第二天-元组的基本使用方法
    Python第二天-list基本功能详解
    Python第一天-str基本功能详解与测试
    while循环
    用户输入
    字典
    if语句
    运算符
  • 原文地址:https://www.cnblogs.com/pantakill/p/6621495.html
Copyright © 2011-2022 走看看