zoukankan      html  css  js  c++  java
  • bzoj1146: [CTSC2008]网络管理Network

      1 #include <iostream>
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 using namespace std;
      7 #define maxn 80005
      8 #define maxk 3200005
      9 #define maxm 160005
     10 #define inf 100000000
     11 
     12 int n,q,sum,a[maxn],root[maxn<<2];
     13 struct Gsegment{
     14     int tot,fa[maxk],son[maxk][2],val[maxk],times[maxk],size[maxk];
     15     void prepare(){tot=0,memset(times,0,sizeof(times));}
     16     int which(int x){return son[fa[x]][1]==x;}
     17     void update(int x){
     18         size[x]=size[son[x][0]]+size[son[x][1]]+times[x];
     19     }
     20     void rotata(int x){
     21         int y=fa[x],d=which(x),dd=which(y);
     22         if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
     23         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
     24         fa[y]=x,son[x][d^1]=y,update(y);
     25     }
     26     void splay(int x,int goal,int op){
     27         while (fa[x]!=goal){
     28             if (fa[fa[x]]==goal) rotata(x);
     29             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
     30             else rotata(x),rotata(x);
     31         }
     32         update(x); if (goal==0) root[op]=x;
     33     }
     34     void insert(int k,int x){
     35         int y=root[k]; bool bo;
     36         if (y==0){
     37             root[k]=++tot,val[tot]=x,times[tot]=size[tot]=1,fa[tot]=son[tot][0]=son[tot][1]=0;
     38             return;
     39         }
     40         for (;;){
     41             bo=0;
     42             if (val[y]==x) times[y]++,size[y]++,bo=1,splay(y,0,k);
     43             else if (x<val[y]){
     44                 if (!son[y][0]) son[y][0]=++tot,val[tot]=x,size[tot]=times[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
     45                 else y=son[y][0];
     46             }else{
     47                 if (!son[y][1]) son[y][1]=++tot,val[tot]=x,size[tot]=times[tot]=1,fa[tot]=y,bo=1,splay(tot,0,k);
     48                 else y=son[y][1];
     49             }
     50             if (bo==1) break;
     51         }
     52     }
     53     void query(int k,int x){
     54         int y=root[k]; if (y==0) return; bool bo;
     55         for (;;){
     56             bo=0;
     57             if (y==0) break;
     58             if (val[y]==x) bo=1,sum+=size[son[y][0]];
     59             else if (x<val[y]) y=son[y][0];
     60             else sum+=(size[son[y][0]]+times[y]),y=son[y][1];
     61             if (bo==1) break;
     62         }
     63     }
     64     int prep(int k,int x){
     65         splay(x,0,k);
     66         int y=son[x][0];
     67         while (son[y][1]) y=son[y][1];
     68         return y;
     69     }
     70     void DLT(int k,int x){
     71         int y=prep(k,x),z;
     72         if (y==0){
     73             splay(x,0,k);
     74             z=son[x][1];
     75             fa[z]=0,root[k]=z,son[x][0]=fa[x]=son[x][1]=times[x]=size[x]=0;
     76         }else{
     77             splay(y,0,k),splay(x,y,k),z=son[x][1];
     78             fa[z]=y,son[y][1]=z,fa[x]=son[x][0]=son[x][1]=size[x]=times[x]=0;
     79             update(y);
     80         }
     81     }
     82     void dlt(int k,int x){
     83         int y=root[k]; if (y==0) return; bool bo;
     84         for (;;){
     85             bo=0;
     86             if (val[y]==x){
     87                 if (times[y]>1) times[y]--,size[y]--,bo=1,splay(y,0,k);
     88                 else times[y]--,size[y]--,bo=1,DLT(k,y);
     89             }else if (x<val[y]) y=son[y][0];
     90             else y=son[y][1];
     91             if (bo==1) break;
     92         }
     93     }
     94 }Splay;//伸展树 
     95 struct Fsegment{
     96     void insert(int k,int l,int r,int x,int y){
     97         Splay.insert(k,y);
     98         if (l==r) return;
     99         int mid=(l+r)>>1;
    100         if (x<=mid) insert(k*2,l,mid,x,y);
    101         else insert(k*2+1,mid+1,r,x,y);
    102     }
    103     void query(int k,int l,int r,int x,int y,int z){
    104         if (l>=x&&r<=y){
    105             Splay.query(k,z);
    106             return;
    107         }int mid=(l+r)>>1;
    108         if (x<=mid) query(k*2,l,mid,x,y,z);
    109         if (y>mid) query(k*2+1,mid+1,r,x,y,z);
    110     }
    111     void change(int k,int l,int r,int x,int y){
    112         Splay.dlt(k,y);
    113         if (l==r) return;
    114         int mid=(l+r)>>1;
    115         if (x<=mid) change(k*2,l,mid,x,y);
    116         else change(k*2+1,mid+1,r,x,y); 
    117     }
    118 }Line_tree;//线段树 
    119 struct Tsegment{
    120     int tot,temp,prep[maxm],son[maxm],hson[maxn],fa[maxn],now[maxn],bz[maxn][20],lo[maxn],top[maxn],size[maxn],deep[maxn],dfn[maxn];
    121     void prepare(){
    122         tot=0,temp=0,memset(now,0,sizeof(now));
    123         memset(fa,0,sizeof(fa));
    124         memset(deep,0,sizeof(deep));
    125         for (int i=1;i<=maxn;i++) lo[i]=log2(i);
    126     }
    127     void add(int x,int y){
    128         prep[++tot]=now[x],now[x]=tot,son[tot]=y;
    129     }
    130     void Add(int x,int y){add(x,y),add(y,x);}
    131     void dfs1(int x){
    132         deep[x]=deep[fa[x]]+1,size[x]=1,bz[x][0]=fa[x];
    133         for (int i=now[x],so=son[i];i;i=prep[i],so=son[i]){
    134             if (so!=fa[x]){
    135                 fa[so]=x,dfs1(so),size[x]+=size[so];
    136                 if (!hson[x]||size[so]>size[hson[x]]) hson[x]=so;
    137             }
    138         }
    139     }
    140     void dfs2(int x){
    141         int v=hson[x];
    142         if (v) dfn[v]=++temp,top[v]=top[x],dfs2(v);
    143         for (int i=now[x],so=son[i];i;i=prep[i],so=son[i]){
    144             if (so!=hson[x]&&so!=fa[x]){
    145                 top[so]=so,dfn[so]=++temp,dfs2(so);
    146             }
    147         }
    148     }
    149     int lca(int x,int y){
    150         if (x==y) return x;
    151         if (deep[x]<deep[y]) swap(x,y);
    152         while (deep[x]!=deep[y]){
    153             x=bz[x][lo[deep[x]-deep[y]]];
    154         }
    155         if (x==y) return x;
    156         while (bz[x][0]!=bz[y][0]){
    157             for (int i=lo[deep[x]];i>=0;i--){
    158                 if (bz[x][i]!=bz[y][i]){
    159                     x=bz[x][i],y=bz[y][i];break;
    160                 }
    161             }
    162         }
    163         return bz[x][0];
    164     }
    165     void build(){
    166         dfs1(1);
    167         temp=0,dfn[1]=++temp,top[1]=1,dfs2(1);
    168         for (int i=1;i<=17;i++){
    169             for (int j=1;j<=n;j++){
    170                 bz[j][i]=bz[bz[j][i-1]][i-1];
    171             }
    172         }
    173 //        for (int i=1;i<=n;i++){
    174 //            for (int j=0;j<=3;j++){
    175 //                printf("%d ",bz[i][j]);
    176 //            }
    177 //            printf("
    ");
    178 //        }
    179         for (int i=1;i<=n;i++) Line_tree.insert(1,1,n,dfn[i],a[i]);
    180     }
    181     int  Query(int x,int y,int z){
    182         sum=0;
    183         for (int t1=top[x],t2=top[y];t1!=t2;x=fa[t1],t1=top[x],t2=top[y]){
    184             if (deep[t1]<deep[t2]) swap(t1,t2),swap(x,y);
    185             Line_tree.query(1,1,n,dfn[t1],dfn[x],z);
    186         }
    187         if (deep[x]>deep[y]) swap(x,y);
    188         Line_tree.query(1,1,n,dfn[x],dfn[y],z);
    189         return sum;
    190     }
    191     void query(int x,int y,int z){
    192 //        printf("%d %d %d
    ",x,y,z);
    193         int tmp=lca(x,y); bool bo=0;
    194         if (deep[x]+deep[y]-2*deep[tmp]+1<z) bo=1,printf("invalid request!
    ");
    195         if (bo==1) return;
    196         z=(deep[x]+deep[y]-2*deep[tmp]+1)-z+1;
    197         int low=0,high=inf,mid,ans=0;
    198         while (low<=high){
    199             mid=(low+high)>>1;
    200             if (Query(x,y,mid)+1<=z) ans=mid,low=mid+1;
    201             else high=mid-1;
    202         }
    203         printf("%d
    ",ans);
    204     }
    205     void change(int x,int y){
    206         Line_tree.change(1,1,n,dfn[x],a[x]),a[x]=y,Line_tree.insert(1,1,n,dfn[x],a[x]);
    207     }
    208 }Tree;//树链剖分
    209 
    210 int main(){
    211     scanf("%d%d",&n,&q);
    212     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    213     int oppo,u,v;
    214     Tree.prepare();
    215     Splay.prepare();
    216     for (int i=1;i<n;i++) scanf("%d%d",&u,&v),Tree.Add(u,v);
    217     Tree.build();
    218     while (q--){
    219         scanf("%d%d%d",&oppo,&u,&v);
    220 //        printf("%d %d %d
    ",oppo,u,v);
    221         if (oppo==0) Tree.change(u,v);
    222         else Tree.query(u,v,oppo);
    223     }
    224     return 0; 
    225 }
    226 /*
    227 5 5
    228 5 1 2 3 4
    229 3 1
    230 2 1
    231 4 3
    232 5 3
    233 2 4 5
    234 0 1 2
    235 2 2 3
    236 2 1 4
    237 3 3 5
    238 
    239 3
    240 2
    241 2
    242 invalid request!
    243 */
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1146

    题目大意:给定一棵n个节点的树,每个点有一个权值,有q个操作,包括如下两种:

    1.询问x,y节点的路径上第k大的权值,若没有k个节点,则输出invalid request!

    2.修改某个节点的权值。

    做法:如果只有操作1,我们考虑用可持久化线段树,毕竟求第k大嘛,那就成了这个题目 bzoj2588: Spoj 10628. Count on a tree,对于这个弱化版的题目,我们用可持久化线段树维护该点到根节点的路径上的权值,sumx+sumy-sumlca-sumfa【lca】即为x,y路径上的信息,然后用BST的性质二分一下就ok了。

    但这题多了一个操作2,即修改某个点的权值,如果用之前的做法,那就会对以该点为根的子树的所有节点产生影响,复杂度极高。

    我们考虑树链剖分+树套树(线段树套splay),线段树维护dfs序区间的点,对于每个线段树节点,套一个splay,维护这段dfs序区间中的权值。

    对于修改操作,在所有包含该点dfs序的splay中先删除原来的权值,再加入新的权值。

    对于询问操作,先转化为第k小,二分答案,树链剖分经典问题,若小于该权值的个数+1<=k,ans=mid,l=mid+1,否则r=mid-1;输出ans即可。

    树链剖分+树套树。

  • 相关阅读:
    网络流24题
    Preliminaries for Benelux Algorithm Programming Contest 2019
    2019 ICPC Asia Xuzhou Regional
    2019 ICPC Asia Nanjing Regional
    后缀自动机学习
    2018 ACM-ICPC 焦作区域赛 E Resistors in Parallel
    2019 ICPC 上海区域赛总结
    LA 3641 Leonardo的笔记本 & UVA 11077 排列统计
    UVA 10294 项链与手镯 (置换)
    CF 1288 E. Messenger Simulator
  • 原文地址:https://www.cnblogs.com/OYzx/p/5539035.html
Copyright © 2011-2022 走看看