zoukankan      html  css  js  c++  java
  • hdu5002 Tree

    动态树的基本操作:

    1. 添边、删边。

    2. 修改一棵树一条链的权值。

    3. 给一棵树一条链的权值加上一个数。

    4. 查询一棵树一条链上的点,第二大权值、权值第二大点的个数。

      1 #include<bits/stdc++.h>
      2 #define lc c[x][0]
      3 #define rc c[x][1]
      4 using namespace std;
      5 const int N=1e5+10;
      6 const int inf=2e9;
      7 int f[N],c[N][2],val[N];
      8 int st[N];
      9 int mx1[N],mx2[N],c1[N],c2[N],siz[N];
     10 int tag_a[N],tag_c[N];
     11 bool rev[N];
     12 
     13 void init(int n){
     14     for(int i=1;i<=n;i++){
     15         f[i]=c[i][0]=c[i][1]=0;
     16         mx1[i]=val[i],mx2[i]=-inf;
     17         c1[i]=1,c2[i]=0;
     18         siz[i]=1;
     19         rev[i]=tag_a[i]=tag_c[i]=0;
     20     }
     21 }
     22 
     23 inline bool nroot(int x){//判断节点是否为一个Splay的根
     24     return c[f[x]][0]==x||c[f[x]][1]==x;
     25 }
     26 
     27 void solve(int x,int v,int cnt){
     28     if(v>mx1[x]) mx2[x]=mx1[x],mx1[x]=v,c2[x]=c1[x],c1[x]=cnt;
     29     else if(v==mx1[x]) c1[x]+=cnt;
     30     else if(v>mx2[x]) mx2[x]=v,c2[x]=cnt;
     31     else if(v==mx2[x]) c2[x]+=cnt;
     32 }
     33 
     34 void add(int x,int v){
     35     val[x]+=v; mx1[x]+=v;
     36     if(mx2[x]!=-inf) mx2[x]+=v;
     37     tag_a[x]+=v;
     38 }
     39 
     40 void change(int x,int v){
     41     val[x]=mx1[x]=v;
     42     mx2[x]=-inf;
     43     c1[x]=siz[x],c2[x]=0;
     44     tag_c[x]=v;
     45     if(tag_a[x]) tag_a[x]=0;
     46 }
     47 
     48 void pushup(int x){//上传信息
     49     mx1[x]=val[x],mx2[x]=-inf;
     50     c1[x]=c2[x]=0;
     51     solve(x,val[x],1);
     52     if(lc) solve(x,mx1[lc],c1[lc]),solve(x,mx2[lc],c2[lc]);
     53     if(rc) solve(x,mx1[rc],c1[rc]),solve(x,mx2[rc],c2[rc]);
     54     siz[x]=siz[lc]+siz[rc]+1;
     55 }
     56 
     57 inline void pushr(int x){//翻转操作
     58     int t=lc;
     59     lc=rc,rc=t;
     60     rev[x]^=1;
     61 }
     62 
     63 void pushdown(int x){//判断并释放懒标记
     64     if(rev[x]){
     65         if(lc) pushr(lc);
     66         if(rc) pushr(rc);
     67         rev[x]=0;
     68     }
     69     if(tag_c[x]!=-inf){
     70         if(lc) change(lc,tag_c[x]);
     71         if(rc) change(rc,tag_c[x]);
     72         tag_c[x]=-inf;
     73     }
     74     if(tag_a[x]){
     75         if(lc) add(lc,tag_a[x]);
     76         if(rc) add(rc,tag_a[x]);
     77         tag_a[x]=0;
     78     }
     79 }
     80 
     81 void rotate(int x){//一次旋转
     82     int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
     83     if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
     84     if(w)f[w]=y;f[y]=x;f[x]=z;
     85     pushup(y);
     86 }
     87 
     88 void splay(int x){
     89     int y=x,z=0;
     90     st[++z]=y;
     91     while(nroot(y)) st[++z]=y=f[y];
     92     while(z) pushdown(st[z--]);
     93     while(nroot(x)){
     94         y=f[x];z=f[y];
     95         if(nroot(y))
     96             rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
     97         rotate(x);
     98     }
     99     pushup(x);
    100 }
    101 
    102 void access(int x){//访问
    103     for(int y=0;x;x=f[y=x])
    104         splay(x),rc=y,pushup(x);
    105 }
    106 
    107 void makeroot(int x){//换根
    108     access(x);splay(x);
    109     pushr(x);
    110 }
    111 
    112 int findroot(int x){//找根(在真实的树中的)
    113     access(x);splay(x);
    114     while(lc)pushdown(x),x=lc;
    115     splay(x);
    116     return x;
    117 }
    118 
    119 void split(int x,int y){//提取路径
    120     makeroot(x);
    121     access(y);splay(y);
    122 }
    123 
    124 void link(int x,int y){//连边
    125     makeroot(x);
    126     if(findroot(y)!=x)f[x]=y;
    127 }
    128 
    129 void cut(int x,int y){//断边
    130     makeroot(x);
    131     if(findroot(y)==x&&f[y]==x&&!c[y][0]){
    132         f[y]=c[x][1]=0;
    133         pushup(x);
    134     }
    135 }
    136 
    137 void query(int x,int y){
    138     split(x,y);
    139     if(c1[y]==siz[y]) printf("ALL SAME
    ");
    140     else printf("%d %d
    ",mx2[y],c2[y]);
    141 }
    142 
    143 int main()
    144 {
    145     int T;
    146     scanf("%d",&T);
    147     for(int cas=1;cas<=T;cas++){
    148         int n,m;
    149         scanf("%d%d",&n,&m);
    150         for(int i=1;i<=n;i++){
    151             scanf("%d",&val[i]);
    152         }
    153         init(n);
    154         for(int i=1;i<n;i++){
    155             int u,v;
    156             scanf("%d%d",&u,&v);
    157             link(u,v);
    158         }
    159         printf("Case #%d:
    ",cas);
    160         while(m--){
    161             int tp;
    162             scanf("%d",&tp);
    163             if(tp==1){
    164                 int x,y,a,b;
    165                 scanf("%d%d%d%d",&x,&y,&a,&b);
    166                 cut(x,y);
    167                 link(a,b);
    168             }
    169             else if(tp==2){
    170                 int a,b,x;
    171                 scanf("%d%d%d",&a,&b,&x);
    172                 split(a,b);
    173                 change(b,x);
    174             }
    175             else if(tp==3){
    176                 int a,b,d;
    177                 scanf("%d%d%d",&a,&b,&d);
    178                 split(a,b);
    179                 add(b,d);
    180             }
    181             else{
    182                 int a,b;
    183                 scanf("%d%d",&a,&b);
    184                 query(a,b);
    185             }
    186         }
    187     }
    188     return 0;
    189 }
  • 相关阅读:
    rabbitMQ 的简单模式
    redis 的发布订阅
    redis 的管道操作
    redis 的其他常用操作
    redis 的链表操作
    redis 的哈希操作
    redis 的字符串操作
    redis 的数据类型
    Redis的基本操作
    day27 的笔记和day 25 的保持一致
  • 原文地址:https://www.cnblogs.com/--HY--/p/13510437.html
Copyright © 2011-2022 走看看