• [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)


    题意:树上单点修改,询问链上k大值。

    思路:

    1.DFS序+树状数组套主席树

    首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息。

    关于询问,就是Que(u)+Que(v)-Que(LCA(u,v))-Que(father(LCA(u,v))),线段树上二分查询第k大即可。

    考虑修改,修改一个点影响到的点为它子树中的所有点,所以要用DFS序。于是这实际上是区间修改单点询问的问题,外面套一层主席树即可。

    $O(nlog^2 n)$

    2.二分+树链剖分+线段树套平衡树

    由于是链上询问,考虑树链剖分。首先二分答案mid,然后问题转化为求mid在这条链上的排名,在树链上用线段树维护,每棵树中维护一棵平衡树,用来求排名。

    $O(nlog^4 n)$理论上会超但实际上常数比较小。

    第一种码力太弱码不出来,写了第二种,速度OJ上倒数(空间倒是十分优秀)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define ls (x<<1)
      5 #define rs (ls|1)
      6 #define lson ls,L,mid
      7 #define rson rs,mid+1,R
      8 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
      9 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     10 using namespace std;
     11 
     12 const int N=100010,M=2000010;
     13 bool vis[N];
     14 int n,Q,cnt,tot,nd,tmp,tim,ans,u,v;
     15 int val[M],lc[M],rc[M],hp[M],sz[M],w[M];
     16 int T[N],pos[N],b[N<<1],fa[N],son[N],dep[N],top[N],root[N<<2];
     17 int h[N],to[N<<1],nxt[N<<1];
     18 struct Que{ int k,a,b; }q[N];
     19 
     20 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
     21 
     22 void dfs1(int x){
     23     sz[x]=1;
     24     For(i,x) if ((k=to[i])!=fa[x]){
     25         fa[k]=x; dep[k]=dep[x]+1; dfs1(k); sz[x]+=sz[k];
     26         if (sz[k]>sz[son[x]]) son[x]=k;
     27     }
     28 }
     29 
     30 void dfs2(int x,int tp){
     31     top[x]=tp; pos[x]=++tim;
     32     if (son[x]) dfs2(son[x],tp);
     33     For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k);
     34 }
     35 
     36 int lca(int u,int v){
     37     for (; top[u]!=top[v]; u=fa[top[u]])
     38         if (dep[top[u]]<dep[top[v]]) swap(u,v);
     39     return (dep[u]<dep[v]) ? u : v;
     40 }
     41 
     42 void rrot(int &x){
     43     int y=lc[x]; lc[x]=rc[y]; rc[y]=x;
     44     sz[y]=sz[x]; sz[x]=sz[lc[x]]+sz[rc[x]]+w[x]; x=y;
     45 }
     46 
     47 void lrot(int &x){
     48     int y=rc[x]; rc[x]=lc[y]; lc[y]=x;
     49     sz[y]=sz[x]; sz[x]=sz[lc[x]]+sz[rc[x]]+w[x]; x=y;
     50 }
     51 
     52 void ins(int &x,int k){
     53     if (!x) { x=++nd; sz[x]=w[x]=1; hp[x]=rand(); val[x]=k; return; }
     54     sz[x]++;
     55     if (k==val[x]) { w[x]++; return; }
     56     if (k<val[x]){ ins(lc[x],k); if (hp[lc[x]]<hp[x]) rrot(x); }
     57     else{ ins(rc[x],k); if (hp[rc[x]]<hp[x]) lrot(x); }
     58 }
     59 
     60 void del(int &x,int k){
     61     if (val[x]==k){
     62         if (w[x]>1) { sz[x]--; w[x]--; return; }
     63         if (!lc[x] || !rc[x]) { x=lc[x]+rc[x]; return; }
     64         if (hp[lc[x]]<hp[rc[x]]) rrot(x),del(x,k);
     65             else lrot(x),del(x,k);
     66         return;
     67     }
     68     sz[x]--;
     69     if (k<val[x]) del(lc[x],k); else del(rc[x],k);
     70 }
     71 
     72 void getrank(int x,int k){
     73     if (!x) return;
     74     if (val[x]==k) tmp+=sz[rc[x]];
     75     else if (k>val[x]) getrank(rc[x],k); else tmp+=sz[rc[x]]+w[x],getrank(lc[x],k);
     76 }
     77 
     78 void mdf(int x,int L,int R,int pos,int a,int b){
     79     if (~a) del(root[x],a); ins(root[x],b);
     80     if (L==R) return;
     81     int mid=(L+R)>>1;
     82     if (pos<=mid) mdf(lson,pos,a,b); else mdf(rson,pos,a,b);
     83 }
     84 
     85 void que(int x,int L,int R,int l,int r,int k){
     86     if (L==l && r==R){ getrank(root[x],k); return; }
     87     int mid=(L+R)>>1;
     88     if (r<=mid) que(lson,l,r,k);
     89     else if (l>mid) que(rson,l,r,k);
     90         else que(lson,l,mid,k),que(rson,mid+1,r,k);
     91 }
     92 
     93 void Get(int x,int f,int k){
     94     while (top[x]!=top[f]) que(1,1,n,pos[top[x]],pos[x],k),x=fa[top[x]];
     95     que(1,1,n,pos[f],pos[x],k);
     96 }
     97 
     98 void solve(int x,int y,int k){
     99     int t=lca(x,y); ans=-1;
    100     if (dep[x]+dep[y]-dep[t]-dep[fa[t]]<k){ puts("invalid request!"); return; }
    101     int L=1,R=tot;
    102     while (L<=R){
    103         int mid=(L+R)>>1;
    104         tmp=0; Get(x,t,mid); Get(y,t,mid);
    105         if (T[t]>mid) tmp--;
    106         if (tmp<k) R=mid-1,ans=mid; else L=mid+1;    
    107     }
    108     printf("%d
    ",b[ans]);
    109 }
    110 
    111 int main(){
    112     freopen("bzoj1146.in","r",stdin);
    113     freopen("bzoj1146.out","w",stdout);
    114     scanf("%d%d",&n,&Q);
    115     rep(i,1,n) scanf("%d",&T[i]),b[++tot]=T[i];
    116     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    117     dep[1]=1; dfs1(1); dfs2(1,1);
    118     rep(i,1,Q){
    119         scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
    120         if (!q[i].k) b[++tot]=q[i].b;
    121     }
    122     sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1;
    123     rep(i,1,n) T[i]=lower_bound(b+1,b+tot+1,T[i])-b;
    124     rep(i,1,Q) if (!q[i].k) q[i].b=lower_bound(b+1,b+tot+1,q[i].b)-b;
    125     rep(i,1,n) mdf(1,1,n,pos[i],-1,T[i]);
    126     rep(i,1,Q)
    127         if (!q[i].k) mdf(1,1,n,pos[q[i].a],T[q[i].a],q[i].b),T[q[i].a]=q[i].b;
    128             else solve(q[i].a,q[i].b,q[i].k);
    129     return 0;
    130 }
  • 相关阅读:
    洛谷$P4768 [NOI2018]$归程 $kruscal$重构树
    洛谷$P2469 [SDOI2010]$ 星际竞速 网络流
    洛谷$P2572 [SCOI2010]$ 序列操作 线段树/珂朵莉树
    $CF914D Bash and a Tough Math Puzzle$ 线段树
    洛谷$P2824 [HEOI2016/TJOI2016]$ 排序 线段树+二分
    洛谷$P$4137 $Rmq Problem / mex$ 主席树
    bat语法
    zabbix监控oracle
    sqlserver常用命令-4
    sqlserver库相关-表相关-3
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9293624.html
Copyright © 2020-2023  润新知