bzoj1146

题解:

主席树+树状数组+树链剖分

树状数组维护修改

树链剖分维护树型结构

主席树维护持久化

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc(x) t[x].l
#define rc(x) t[x].r
typedef long long ll;
const int N=8e4+5;
int deep[N],fa[N],mx[N],size[N],top[N],tid[N],tot,L[N],R[N];
int A[N<<1],B[N<<1],a,b,crt[N],rt[N],sz,h[N],cnt,n,Q,w[N],u,v,k,mp[N<<1],m;
struct node{int l,r,w;}t[N*128];
struct ques{int k,a,b;}q[N];
struct edge{int v,ne;}e[N<<1];
int ef(int v)
{
    int l=1,r=m;
    while(l<r)
     {
        int mid=(l+r)/2;
        if (mp[mid]<v)l=mid+1;
        else r=mid;
     }
    return l;
}
void ins(int u,int v)
{
    e[++cnt].v=v;
    e[cnt].ne=h[u];
    h[u]=cnt;
}
void dfs(int u)
{
    size[u]=1;
    for(int i=h[u];i;i=e[i].ne)
     {
        int v=e[i].v;
        if(v==fa[u]) continue;
        fa[v]=u;deep[v]=deep[u]+1;
        dfs(v);
        size[u]+=size[v];
        if(size[v]>size[mx[u]]) mx[u]=v;
     }
}
void dfs(int u,int anc)
{
    if(!u) return;
    tid[u]=L[u]=++tot;
    top[u]=anc;
    dfs(mx[u],anc);
    for (int i=h[u];i;i=e[i].ne)
     if (e[i].v!=fa[u]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v);
    R[u]=tot;
}
int lca(int x,int y)
{
    while (top[x]!=top[y])
     {
        if (deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
     }
    if (tid[x]>tid[y]) swap(x,y);
    return x;
}
void ins(int &x,int l,int r,int p,int d)
{
    t[++sz]=t[x];x=sz;
    t[x].w+=d;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (p<=mid) ins(lc(x),l,mid,p,d);
    else ins(rc(x),mid+1,r,p,d);
}
void build(int u)
{
    if (!u) return;
    rt[u]=rt[fa[u]];
    ins(rt[u],1,m,w[u],1);
    build(mx[u]);
    for (int i=h[u];i;i=e[i].ne)
     if (e[i].v!=fa[u]&&e[i].v!=mx[u]) build(e[i].v);
}
void add(int x,int v,int d)
{
    for (int i=x;i<=tot;i+=i&-i) ins(crt[i],1,m,v,d);
}
bool check(int k)
{
    int suml=0,sumr=0;
    for (int i=1;i<=a;i++) suml+=t[A[i]].w;
    for (int i=1;i<=b;i++) sumr+=t[B[i]].w;
    return sumr-suml>=k;
}
int cal()
{
    int suml=0,sumr=0;
    for (int i=1;i<=a;i++) suml+=t[rc(A[i])].w;
    for (int i=1;i<=b;i++) sumr+=t[rc(B[i])].w;
    return sumr-suml;
}
void query(int ql,int qr,int k)
{
    a=b=0;int p=lca(ql,qr);
    B[++b]=rt[ql];B[++b]=rt[qr];
    A[++a]=rt[p];A[++a]=rt[fa[p]];
    for (int i=L[ql];i;i-=i&-i) B[++b]=crt[i];
    for (int i=L[qr];i;i-=i&-i) B[++b]=crt[i];
    for (int i=L[p];i;i-=i&-i) A[++a]=crt[i];
    for (int i=L[fa[p]];i;i-=i&-i) A[++a]=crt[i];
    if (!check(k)){puts("invalid request!");return;}
    int l=1,r=m;
    while (l<r)
    {
        int mid=(l+r)>>1,rsize=cal();
        if (rsize>=k)
         {
            l=mid+1;
            for (int i=1;i<=a;i++) A[i]=rc(A[i]);
            for (int i=1;i<=b;i++) B[i]=rc(B[i]);
         }
        else
         {
            r=mid;
            k-=rsize;
            for (int i=1;i<=a;i++) A[i]=lc(A[i]);
            for (int i=1;i<=b;i++) B[i]=lc(B[i]);
         }
    }
    printf("%d
",mp[l]);
}
int main() 
{
    scanf("%d%d",&n,&Q);
    for (int i=1;i<=n;i++)scanf("%d",&w[i]),mp[++m]=w[i];
    for (int i=1;i<=n-1;i++)scanf("%d%d",&u,&v),ins(u,v),ins(v,u);
    dfs(1);dfs(1,1);
    for (int i=1;i<=Q;i++)
     {
         scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b);
        if (q[i].k==0) mp[++m]=q[i].b;
     }
    sort(mp+1,mp+1+m);
    int p=0;mp[++p]=mp[1];
    for (int i=2;i<=m;i++)
     if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
    m=p;
    for (int i=1;i<=n;i++) w[i]=ef(w[i]);
    build(1);
    for (int i=1;i<=Q;i++)
     {
        int k=q[i].k,a=q[i].a,b=q[i].b;
        if (k==0)
         {
            add(L[a],w[a],-1);add(R[a]+1,w[a],1);
            w[a]=ef(b);
            add(L[a],w[a],1);add(R[a]+1,w[a],-1);
         }
        else query(a,b,k);
     }
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8011864.html