• caioj1442:第k小的数Ⅱ


    【传送门:caioj1442


    简要题意:

      给出n个点,每个点都有一个权值,m个操作,操作有两种:第一种是询问l到r的第k小的值,然后输出这个值,第二种是将第x个点的值改为k


    题解:

      又是一道主席树的例题,不过简直比前两题(caioj1441,caioj1443)难不止一点点

      看到第一种操作,我们可以用主席树来搞,但是第二种操作的话,我们就要用树状数组来维护每个第二种操作所带来的影响,而且每次要求第一种操作的时候都要先在树状数组中找到相应的点,然后再处理主席树


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    using namespace std;
    int a[210000];
    struct node
    {
        int lc,rc,c;
    }tr[3100000];int cnt;
    int rt[210000];int n;
    int ust[210000];//树状数组 
    int lowbit(int x)//树状数组用来找上司或下属 
    {
        return x&-x;
    }
    void Link(int &u,int l,int r,int p,int c)
    {
        if(u==0) u=++cnt;
        tr[u].c+=c;
        if(l==r) return ;
        int mid=(l+r)/2;
        if(p<=mid) Link(tr[u].lc,l,mid,p,c);
        else Link(tr[u].rc,mid+1,r,p,c);
    }
    void Merge(int &u1,int u2)
    {
        if(u1==0){u1=u2;return ;}
        if(u2==0) return ;
        tr[u1].c+=tr[u2].c;
        Merge(tr[u1].lc,tr[u2].lc);
        Merge(tr[u1].rc,tr[u2].rc);
    }
    void Turn(int u,int c)//树状数组的实时更新 
    //c==-1时树状数组记录每个点所在线段树的根
    //c==0时记录左孩子
    //c==1时记录右孩子 
    {
        while(u>=n+1)
        {
            if(c==-1) ust[u]=rt[u];
            else if(c==0) ust[u]=tr[ust[u]].lc;
            else if(c==1) ust[u]=tr[ust[u]].rc;
            u-=lowbit(u);
        }
    }
    void Modefy(int u,int p,int c)//对于修改值就用树状数组来节约时间 
    {
        while(u<=2*n)
        {
            Link(rt[u],0,1000000000,p,c);
            u+=lowbit(u);
        }
    }
    int Getsum(int u)//求出修改过后树状数组得到的值 
    {
        int ret=0;
        while(u>=n+1)
        {
            ret+=tr[tr[ust[u]].lc].c;
            u-=lowbit(u);
        }
        return ret;
    }
    int Ask(int u1,int u2,int p1,int p2,int l,int r,int p)
    {
        if(l==r) return l;
        int c=tr[tr[u2].lc].c-tr[tr[u1].lc].c+Getsum(p2+n)-Getsum(p1+n);
        int mid=(l+r)/2;
        if(p<=c)
        {
            Turn(p1+n,0);
            Turn(p2+n,0);
            return Ask(tr[u1].lc,tr[u2].lc,p1,p2,l,mid,p);
        }
        else
        {
            Turn(p1+n,1);
            Turn(p2+n,1);
            return Ask(tr[u1].rc,tr[u2].rc,p1,p2,mid+1,r,p-c);
        }
    }
    int main()
    {
        int m;
        scanf("%d%d",&n,&m);
        cnt=0;memset(rt,0,sizeof(rt));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            Link(rt[i],0,1000000000,a[i],1);
            Merge(rt[i],rt[i-1]);
        }
        char st[2];
        for(int i=1;i<=m;i++)
        {
            scanf("%s",st+1);
            if(st[1]=='Q')
            {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                Turn(l+n-1,-1);
                Turn(r+n,-1);
                printf("%d
    ",Ask(rt[l-1],rt[r],l-1,r,0,1000000000,k));
            }
            else
            {
                int p,c;
                scanf("%d%d",&p,&c);
                Modefy(p+n,a[p],-1);
                a[p]=c;
                Modefy(p+n,a[p],1);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    两层和三层的讨论(C/S)
    FF IE 编码 转换
    MySql数据库 字符编码问题解决办法
    JDO的persistence by reachability
    技术贴
    Eclipse 快捷键总结
    记录一下: 火狐 IE 实现图片本地预览 demo
    一般jsp 翻页 选择 保留 代码
    复习下几个排序
    Eclipse 插件开发 资料贡献
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7718757.html
Copyright © 2020-2023  润新知