【主席树】 ZOJ 2112 Dynamic Rankings 区间第k小值

来源:互联网 发布:c语言文件加密程序 编辑:程序博客网 时间:2024/05/22 02:14

点击打开链接

题解:Empress

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <iostream>#include <algorithm>#include <sstream>#include <cmath>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include<bitset>#include <set>#include <map>#define clc(arr, val)    memset(arr, val, sizeof(arr))#define FOR(i,a,b)  for(int i=a;i<=b;i++)#define IN   freopen ("in.txt" , "r" , stdin);#define OUT  freopen ("out.txt" , "w" , stdout);typedef long long  LL;typedef unsigned long long  ULL;const int MAXN = 60000;const int MAXM = 6000010;const int INF = 0x3f3f3f3f;const LL mod = (LL)1<<32;const double eps= 1e-8;const double pi=acos(-1.0);#define lson l,m, rt<<1#define rson m+1,r,rt<<1|1int Hash[MAXN],a[MAXN],all,tol,n;int T[MAXN],S[MAXN],L[MAXN<<5],R[MAXN<<5],sum[MAXN<<5];int build(int l,int r){    int rt=(++all);    sum[rt]=0;    if(l==r) return rt;    int m=(l+r)>>1;    L[rt]=build(l,m);    R[rt]=build(m+1,r);    return rt;}int update(int pre,int x,int val,int l,int r){    int rt=(++all);    L[rt]=L[pre],R[rt]=R[pre],sum[rt]=sum[pre]+val;    if(l==r) return rt;    int m=(l+r)>>1;    if(x<=m)        L[rt]=update(L[pre],x,val,l,m);    else R[rt]=update(R[pre],x,val,m+1,r);    return rt;}/***树状数组*****/int use[MAXN];int lowbit(int x){    return x&(-x);}void add(int x, int pos, int val){    while(x<=n)    {        S[x]=update(S[x], pos, val, 1, tol);        x+=lowbit(x);    }}int Sum(int x){    int ret=0;    while(x>0)    {        ret+=sum[L[use[x]]];        x-=lowbit(x);    }    return ret;}void modify(int x, int p, int d){    while(x<=n)    {        S[x]=update(S[x], p, d, 1, tol);        x+=lowbit(x);    }}/****query***/int query(int left,int right,int lr,int rr,int k,int l,int r){    if(l==r) return l;    int m=(l+r)>>1;    int num=Sum(right)-Sum(left)+sum[L[rr]]-sum[L[lr]];    if(k<=num)    {        for(int i=left;i;i-=lowbit(i))            use[i]=L[use[i]];        for(int i=right;i;i-=lowbit(i))            use[i]=L[use[i]];        return query(left,right,L[lr],L[rr],k,l,m);    }    else    {        for(int i=left;i;i-=lowbit(i))            use[i]=R[use[i]];        for(int i=right;i;i-=lowbit(i))            use[i]=R[use[i]];        return query(left,right,R[lr],R[rr],k-num,m+1,r);    }}/*******询问*****/struct node{    int op,l,r,k;}Q[10100];int main(){    int m,t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        all=0;        for(int i=1;i<=n;++i)        {            scanf("%d",&a[i]);            Hash[++all]=a[i];        }        for(int i=0;i<m;i++)//save query        {            char op[2];            scanf("%s",op);            if(op[0]=='Q')            {                scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].k);                Q[i].op=1;            }            else             {                scanf("%d%d",&Q[i].l,&Q[i].r);                Hash[++all]=Q[i].r;                Q[i].op=0;            }        }        sort(Hash+1,Hash+all+1);        tol=unique(Hash+1,Hash+all+1)-Hash-1;        T[0]=build(1,tol);        for(int i=1;i<=n;i++)//build tree        {            int x=lower_bound(Hash+1,Hash+tol+1,a[i])-Hash;            T[i]=update(T[i-1],x,1,1,tol);            S[i]=T[0];        }        for(int i=0;i<m;i++)//output query        {            if(Q[i].op)//Query            {                for(int j=Q[i].l-1;j;j-=lowbit(j))                    use[j]=S[j];                for(int j=Q[i].r;j;j-=lowbit(j))                    use[j]=S[j];                int x=query(Q[i].l-1,Q[i].r,T[Q[i].l-1],T[Q[i].r],Q[i].k,1,tol);                printf("%d\n",Hash[x]);            }            else //Change            {                modify(Q[i].l, lower_bound(Hash+1, Hash+tol+1, a[Q[i].l])-Hash, -1);                modify(Q[i].l, lower_bound(Hash+1, Hash+tol+1, Q[i].r)-Hash, 1);                a[Q[i].l]=Q[i].r;            }        }    }    return 0;}/**/


0 0