• 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;
    }
  • 相关阅读:
    【python】带图片验证码的登录自动化实战
    【Python】输入一个整数N,求1到N个整数的十进制表示中某个字符出现的次数
    【Python】input()与sys.stdin()使用比较
    【Python】爬虫之使用etree进行xpath元素定位
    python:读取数据库+图片上增加文字
    H5介绍与测试设计
    【OpenCV-Python:实现人脸、人眼、嘴巴识别】实战(一)
    ASCII、Unicode、GBK和UTF-8字符编码的区别联系
    Python基础语法学习笔记
    Python基础知识符和操作符_学习笔记
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8011864.html
Copyright © 2020-2023  润新知