zoukankan      html  css  js  c++  java
  • 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”

    题面:月下“毛景树”

    题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好)。用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了;前三个更新的操作都可以合并起来,可以发现a到b节点间的边权max实质是a节点到b节点的路径中a下移一位后到b节点的点权max,意味着:若dep[a]<dep[b](若不是这样可交换),找点权max上跳时不能到LCA(a,b);因为重边会是连续的,所以直接(seg记录节点在线段树中的下标)seg[a]+1到seg[b]就可以了。然后要注意flag1和flag2的维护顺序以及相互的影响。

    _(:3J∠)_语文太差了,不好意思

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #define max(a,b) ((a)>(b)?(a):(b))
      5 using namespace std;
      6 const int maxn=100005,maxm=100005;
      7 int N,W[maxn],num_edge=0,edge_head[maxn],a,b,c,seg[maxn],rev[maxn],fa[maxn],top[maxn],son[maxn],size[maxn];
      8 int dep[maxn],Ans;
      9 bool E[maxm<<1];
     10 char o[20];
     11 inline int rd(){
     12     int x=0,f=1;char c=getchar();
     13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     14     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     15     return f*x;
     16 }
     17 struct Edge{
     18     int from,to,nx,dis;
     19 }edge[maxm<<1];
     20 inline void Add_edge(int from,int to,int dis){
     21     edge[++num_edge].nx=edge_head[from];
     22     edge[num_edge].from=from;
     23     edge[num_edge].to=to;
     24     edge[num_edge].dis=dis;
     25     edge_head[from]=num_edge;
     26     return;
     27 }
     28 inline void Dfs(int x,int f){
     29     for(int i=edge_head[x];i;i=edge[i].nx){
     30         int y=edge[i].to;
     31         if(y!=f){
     32             W[y]=edge[i].dis;
     33             E[i]=1;
     34             Dfs(y,x);
     35         }
     36     }
     37     return;
     38 }
     39 inline void Dfs1(int x,int f){
     40     size[x]=1;
     41     dep[x]=dep[f]+1;
     42     fa[x]=f;
     43     for(int i=edge_head[x];i;i=edge[i].nx){
     44         int y=edge[i].to;
     45         if(y!=f){
     46             Dfs1(y,x);
     47             size[x]+=size[y];
     48             if(size[y]>size[son[x]])son[x]=y;
     49         }
     50     }
     51     return;
     52 }
     53 inline void Dfs2(int x){
     54     if(son[x]){
     55         int y=son[x];
     56         seg[y]=++seg[0];
     57         rev[seg[0]]=y;
     58         top[y]=top[x];
     59         Dfs2(y);
     60     }
     61     for(int i=edge_head[x];i;i=edge[i].nx){
     62         int y=edge[i].to;
     63         if(top[y]==0){
     64             seg[y]=++seg[0];
     65             rev[seg[0]]=y;
     66             top[y]=y;
     67             Dfs2(y);
     68         }
     69     }
     70     return;
     71 }
     72 struct Tree{
     73     int l,r,maxs,flag1,flag2;
     74 }t[maxn<<3];
     75 inline void Build(int k,int l,int r){
     76     t[k].l=l;t[k].r=r;
     77     if(l==r){
     78         t[k].maxs=W[rev[l]];
     79         return;
     80     }
     81     int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1;
     82     Build(ls,l,mid);Build(rs,mid+1,r);
     83     t[k].maxs=max(t[ls].maxs,t[rs].maxs);
     84     return;
     85 }
     86 inline void Pushdown(int k){
     87     int ls=k<<1,rs=k<<1|1,flag1=t[k].flag1,flag2=t[k].flag2;
     88     if(flag1){
     89         t[ls].maxs=t[rs].maxs=t[ls].flag1=t[rs].flag1=flag1;
     90         t[ls].flag2=t[rs].flag2=0;
     91         t[k].flag1=0;
     92     }
     93     if(flag2){
     94         t[ls].maxs+=flag2;t[rs].maxs+=flag2;
     95         t[ls].flag2+=flag2;t[rs].flag2+=flag2;
     96         t[k].flag2=0;
     97     }
     98     return;
     99 }
    100 inline void Update(int k,int ql,int qr,int v,int o){
    101     int l=t[k].l,r=t[k].r;
    102     if(ql<=l&&r<=qr){
    103         if(o==0){
    104             t[k].maxs=v;
    105             t[k].flag1=v;
    106             t[k].flag2=0;
    107         }
    108         else {
    109             t[k].maxs+=v;
    110             t[k].flag2+=v;
    111         }
    112         return;
    113     }
    114     int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1;
    115     Pushdown(k);
    116     if(ql<=mid)Update(ls,ql,qr,v,o);
    117     if(mid+1<=qr)Update(rs,ql,qr,v,o);
    118     t[k].maxs=max(t[ls].maxs,t[rs].maxs);
    119     return;
    120 }
    121 inline void Query(int k,int ql,int qr){
    122     int l=t[k].l,r=t[k].r;
    123     if(ql<=l&&r<=qr){
    124         Ans=max(Ans,t[k].maxs);
    125         return;
    126     }
    127     int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1;
    128     Pushdown(k);
    129     if(ql<=mid)Query(ls,ql,qr);
    130     if(mid+1<=qr)Query(rs,ql,qr);
    131     return;
    132 }
    133 inline void Solve(int x,int y,int v,int o){
    134     int fx=top[x],fy=top[y];
    135     while(fx!=fy){
    136         if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
    137         if(o!=2)Update(1,seg[fx],seg[x],v,o);
    138         else Query(1,seg[fx],seg[x]);
    139         x=fa[top[x]];fx=top[x];
    140     }
    141     if(dep[x]>dep[y])swap(x,y);
    142     if(seg[x]==seg[y])return;
    143     if(o!=2)Update(1,seg[x]+1,seg[y],v,o);
    144     else Query(1,seg[x]+1,seg[y]);
    145     return;
    146 }
    147 int main(){
    148     N=rd();
    149     for(int i=1;i<N;i++){
    150         a=rd();b=rd();c=rd();
    151         Add_edge(a,b,c);
    152         Add_edge(b,a,c);
    153     }
    154     Dfs(1,0);
    155     Dfs1(1,0);
    156     seg[0]=seg[1]=rev[1]=top[1]=1;
    157     Dfs2(1);
    158     Build(1,1,N);
    159     scanf("%s",o);
    160     while(o[0]!='S'){
    161         a=rd();b=rd();
    162         if(o[0]!='M'){
    163             if(o[1]=='h'){//Change
    164                 if(E[a*2-1])Solve(edge[a*2-1].from,edge[a*2-1].to,b,0);
    165                 else Solve(edge[a*2].from,edge[a*2].to,b,0);
    166             }
    167             else if(o[1]=='o'){//Cover
    168                 c=rd();
    169                 Solve(a,b,c,0);
    170             }
    171             else{//Add
    172                 c=rd();
    173                 Solve(a,b,c,1);
    174             }
    175         }
    176         else{//Max
    177             Ans=0;
    178             Solve(a,b,-1,2);
    179             printf("%d
    ",Ans);
    180         }
    181         scanf("%s",o);
    182     }
    183     return 0;
    184 }

    By:AlenaNuna

  • 相关阅读:
    linux网络编程之socket编程(三)
    linux网络编程之socket编程(二)
    字符串转成时间戳
    xls的读写
    统计词语频率保存到xls
    信息时代的学习(对于人类)
    编码格式简介:ASCII码、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM头
    ThinkPHP中:RBAC权限控制的实习步骤
    getField()和select()方法的区别
    按钮美化,变化显示效果
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10187580.html
Copyright © 2011-2022 走看看