码迷,mamicode.com
首页 > 其他好文 > 详细

【刷题】BZOJ 1901 Zju2112 Dynamic Rankings

时间:2018-03-22 17:31:02      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:air   return   desc   val   ble   输出   begin   insert   char   

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。

Input

第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。
分别表示序列的长度和指令的个数。
第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。
接下来的m行描述每条指令
每行的格式是下面两种格式中的一种。
Q i j k 或者 C i t
Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)
表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t
m,n≤10000

Output

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Sample Input

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6

Solution

这是一道树套树的题目,树状数组套主席树
从最基本的开始
找区间第\(k\)大,主席树
如果我们对于修改直接暴力做,那么正确性保证,但复杂度不能承受
那么我们就想什么东西可以帮助主席树维护动态的前缀和(静态的查询其实主席树自己就把前缀和做了),而查询第\(k\)大的事情还是由主席树做
于是我们就想到了BIT(树状数组)
常用的BIT可以支持单点修改求前缀和
那么我们把BIT的“点”变成主席树的“树”,就可以完成这道题了

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
#define left 0
#define right 1
const int MAXN=10000+10;
int n,m,A[MAXN];
struct node{
    char opt;
    int i,j,k,t;
};
node Q[MAXN];
std::vector<int> V;
std::map<int,int> M;
struct ChairManTree_BIT{
    int cnt,lc[MAXN<<9],rc[MAXN<<9],num[MAXN<<9],root[MAXN],need[2][20],nt[2],size;
    inline void init()
    {
        cnt=0;
        memset(lc,0,sizeof(lc));
        memset(rc,0,sizeof(rc));
        memset(num,0,sizeof(num));
    }
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    inline void Insert(int &rt,int l,int r,int pos,int val)
    {
        if(!rt)rt=++cnt;
        num[rt]+=val;
        if(l==r)return ;
        else
        {
            if(pos<=Mid)Insert(lc[rt],lson,pos,val);
            else Insert(rc[rt],rson,pos,val);
        }
    }
    inline void add(int x,int k,int p)
    {
        while(x<=n)
        {
            Insert(root[x],1,size,k,p);
            x+=lowbit(x);
        }
    }
    inline void Gneed(int nxt[])
    {
        for(register int i=1;i<=nt[left];++i)need[left][i]=nxt[need[left][i]];
        for(register int i=1;i<=nt[right];++i)need[right][i]=nxt[need[right][i]];
    }
    inline int Query(int l,int r,int k)
    {
        if(l==r)return l;
        else
        {
            int t=0;
            for(register int i=1;i<=nt[right];++i)t+=num[lc[need[right][i]]];
            for(register int i=1;i<=nt[left];++i)t-=num[lc[need[left][i]]];
            if(k<=t)
            {
                Gneed(lc);
                return Query(lson,k);
            }
            else
            {
                Gneed(rc);
                return Query(rson,k-t);
            }
        }
    }
    inline int sum(int l,int r,int k)
    {
        nt[left]=nt[right]=0;
        l--;
        while(l>0)
        {
            need[left][++nt[left]]=root[l];
            l-=lowbit(l);
        }
        while(r>0)
        {
            need[right][++nt[right]]=root[r];
            r-=lowbit(r);
        }
        return Query(1,size,k);
    }
};
ChairManTree_BIT T;
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void newnum(int &x)
{
    int pre=x;
    x=lower_bound(V.begin(),V.end(),x)-V.begin()+1;
    M[x]=pre;
}
inline void discre()
{
    std::sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    T.size=V.size();
    for(register int i=1;i<=n;++i)newnum(A[i]);
    for(register int i=1;i<=m;++i)
        if(Q[i].opt=='C')newnum(Q[i].t);
}
int main()
{
    read(n);read(m);
    for(register int i=1;i<=n;++i)
    {
        read(A[i]);
        V.push_back(A[i]);
    }
    for(register int i=1;i<=m;++i)
    {
        std::cin>>Q[i].opt;
        if(Q[i].opt=='Q')read(Q[i].i),read(Q[i].j),read(Q[i].k);
        else
        {
            read(Q[i].i),read(Q[i].t);
            V.push_back(Q[i].t);
        }
    }
    discre();
    T.init();
    for(register int i=1;i<=n;++i)T.add(i,A[i],1);
    for(register int i=1;i<=m;++i)
    {
        if(Q[i].opt=='Q')write(M[T.sum(Q[i].i,Q[i].j,Q[i].k)],'\n');
        if(Q[i].opt=='C')
        {
            T.add(Q[i].i,A[Q[i].i],-1);
            A[Q[i].i]=Q[i].t;
            T.add(Q[i].i,A[Q[i].i],1);
        }
    }
    return 0;
}

【刷题】BZOJ 1901 Zju2112 Dynamic Rankings

标签:air   return   desc   val   ble   输出   begin   insert   char   

原文地址:https://www.cnblogs.com/hongyj/p/8624340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!