• 【LSGDOJ1834 Tree】树链剖分


    题目描述

    给定一个N个结点的无向树,树中的结点按照1...N编号,树中的边按照1...N − 1编号,每条边都赋予一个权值。你需要编写程序支持以下三种操作:
    1.    CHANGE i v:将i号边的权值改为v
    2.    NEGATE a b:将结点a到结点b路径上每条边权值取相反数。例如NEGATE(-3)=3,
    NEGATE(3)=-3。
    3.    QUERY a b:返回结点a到结点b路径上权值最大边的权值。

    输入

    第一行为N(≤ 105),代表树中结点的个数。
    接下来− 1行,每行三个整数x y w表示有一条连接结点xy的边,权值为w
    接下来若干行代表了三种操作。操作的格式见问题描述。遇到一行“DONE”时结束。
    不会超过105个操作(不包含DONE)。
    输入数据中有30%的数据,满足≤ 100。

    输出

    对于每个QUERY操作,输出一行,代表最大的权值。

    样例输入

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

    样例输出

    1 3
     
    题解:
    树链剖分水题,但小测的时候打错了,发个博客以泄愤。
    关键:线段树中不仅维护最大值又要维护最小值,然后取反就相当于swap(最小值,最大值).
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #define ls (node<<1)
      7 #define rs (node<<1|1)
      8 using namespace std;
      9 const int N=100005,INF=1999999999;
     10 int n;
     11 int gi()
     12 {
     13     int str=0,f=1;char ch=getchar();
     14     while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
     16     return str*f;
     17 }
     18 int num=0,head[N],haha[N];char s[15];
     19 struct TT{
     20     int minn,maxn;
     21 }Tree[N*4];
     22 int mark[N*4];
     23 struct Lin{
     24     int next,to,dis;
     25 }a[N*2];
     26 struct Edge{
     27     int x,y,z;
     28 }e[N];
     29 void updata(int node){
     30     Tree[node].maxn=Tree[ls].maxn>Tree[rs].maxn?Tree[ls].maxn:Tree[rs].maxn;
     31     Tree[node].minn=Tree[ls].minn<Tree[rs].minn?Tree[ls].minn:Tree[rs].minn;
     32 }
     33 void init(int x,int y,int z)
     34 {
     35     a[++num].next=head[x];
     36     a[num].to=y;
     37     a[num].dis=z;
     38     head[x]=num;
     39     a[++num].next=head[y];
     40     a[num].to=x;
     41     a[num].dis=z;
     42     head[y]=num;
     43 }
     44 int top[N],dep[N],id[N],son[N],fa[N],size[N],ids=0;
     45 void dfs1(int x)
     46 {
     47     int u;
     48     size[x]=1;
     49     for(int i=head[x];i;i=a[i].next)
     50     {
     51         u=a[i].to;
     52         if(dep[u])continue;
     53         dep[u]=dep[x]+1;fa[u]=x;
     54         dfs1(u);
     55         size[x]+=size[u];if(size[u]>size[son[x]])son[x]=u;
     56     }
     57 }
     58 void dfs2(int x,int tp)
     59 {
     60     id[x]=++ids;top[x]=tp;
     61     if(son[x])dfs2(son[x],tp);
     62     int u;
     63     for(int i=head[x];i;i=a[i].next){
     64         u=a[i].to;
     65         if(u==son[x] || u==fa[x])continue;
     66         dfs2(u,u);
     67     }
     68 }
     69 void build(int l,int r,int node)
     70 {
     71     mark[node]=0;
     72     if(l==r){Tree[node].maxn=Tree[node].minn=haha[l];return ;}
     73     int mid=(l+r)>>1;
     74     build(l,mid,ls);
     75     build(mid+1,r,rs);
     76     updata(node);
     77 }
     78 void pushdown(int node)
     79 {
     80     if(!mark[node])return ;
     81     mark[ls]^=1;mark[rs]^=1;
     82     swap(Tree[rs].maxn,Tree[rs].minn);Tree[ls].maxn*=-1;Tree[ls].minn*=-1;
     83     swap(Tree[ls].maxn,Tree[ls].minn);Tree[rs].maxn*=-1;Tree[rs].minn*=-1;
     84     mark[node]=0;
     85 }
     86 void cg(int l,int r,int node,int sa,int se,int toit)
     87 {
     88     if(l>se || r<sa)return ;
     89     if(sa<=l && r<=se){
     90         if(toit==INF){mark[node]^=1;swap(Tree[node].maxn,Tree[node].minn);Tree[node].maxn*=-1;Tree[node].minn*=-1;}
     91         else {Tree[node].maxn=Tree[node].minn=toit;}
     92         return ;
     93     }
     94     pushdown(node);
     95     int mid=(l+r)>>1;
     96     cg(l,mid,ls,sa,se,toit);
     97     cg(mid+1,r,rs,sa,se,toit);
     98     updata(node);
     99 }
    100 void Change(int x,int y){
    101     cg(1,n,1,id[e[x].x],id[e[x].x],y);
    102 }
    103 void Negdata(int x,int y)
    104 {
    105     while(top[x]!=top[y]){
    106         if(dep[top[x]]<dep[top[y]])swap(x,y);
    107         cg(1,n,1,id[top[x]],id[x],INF);
    108         x=fa[top[x]];
    109     }
    110     if(dep[x]<dep[y])swap(x,y);
    111     cg(1,n,1,id[y]+1,id[x],INF);
    112     return ;
    113 }
    114 int getsum(int l,int r,int node,int sa,int se)
    115 {
    116     if(l>se || r<sa)return -INF;
    117     if(sa<=l && r<=se)return Tree[node].maxn;
    118     pushdown(node);
    119     int mid=(l+r)>>1;
    120     return max(getsum(l,mid,ls,sa,se),getsum(mid+1,r,rs,sa,se));
    121     updata(node);
    122 }
    123 int Ask(int x,int y)
    124 {
    125     int ans=-INF,tmp;
    126     while(top[x]!=top[y]){
    127         if(dep[top[x]]<dep[top[y]])swap(x,y);
    128         tmp=getsum(1,n,1,id[top[x]],id[x]);
    129         if(tmp>ans)ans=tmp;
    130         x=fa[top[x]];
    131     }
    132     if(dep[x]<dep[y])swap(x,y);
    133     tmp=getsum(1,n,1,id[y]+1,id[x]);
    134     return max(tmp,ans);
    135 }
    136 int main()
    137 {
    138     n=gi();
    139     int x,y;
    140     for(int i=1;i<n;i++){
    141         e[i].x=gi();e[i].y=gi();e[i].z=gi();
    142         init(e[i].x,e[i].y,e[i].z);
    143     }
    144     dep[1]=1;dfs1(1);dfs2(1,1);fa[1]=1;haha[1]=-INF;
    145     for(int i=1;i<n;i++){
    146         x=e[i].x;y=e[i].y;
    147         if(dep[x]<dep[y])swap(x,y),swap(e[i].x,e[i].y);
    148         haha[id[x]]=e[i].z;
    149     }
    150     build(1,n,1);
    151     while(1)
    152     {
    153         scanf("%s%d%d",s,&x,&y);
    154         if(s[0]=='D')break;
    155         if(s[0]=='C')Change(x,y);
    156         else if(s[0]=='N')Negdata(x,y);
    157         else if(s[0]=='Q')printf("%d
    ",Ask(x,y));
    158     }
    159     return 0;
    160 }
  • 相关阅读:
    元组转换列表
    python切片
    序列类型的方法 增删改查
    python基础 四则运算和数据类型
    linux 常用基础命令操作
    MySQL 命令操作
    linux中如何修改root密码、设置固定IP、安装vmware tools
    虚拟机中网络桥接模式设置
    PHP基础
    HTML基本标签介绍
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6873950.html
Copyright © 2020-2023  润新知