bzoj1901: Zju2112 Dynamic Rankings

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1901

题解:树套树,线段树+treap(sb的我以为有多组数据。。。。。。呃呵呵呵狂RE)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#define N 200001
#define M 1300001
#define inf 1000000000
using namespace std;
int n,m,sz,ans,a[N];
int ls[M],rs[M],rnd[M],v[M],s[M],w[M];
int root[N];
int read()
{
    int x=0; char ch; bool bo=0;
    while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
    while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
    if (bo) return -x; return x;
}
void updata(int k){s[k]=s[ls[k]]+s[rs[k]]+w[k];}
void rturn(int &k){int t=ls[k]; ls[k]=rs[t]; rs[t]=k; s[t]=s[k]; updata(k); k=t;}
void lturn(int &k){int t=rs[k]; rs[k]=ls[t]; ls[t]=k; s[t]=s[k]; updata(k); k=t;}
void insert(int &k,int num)
{
    if (!k) {k=++sz; s[k]=w[k]=1; v[k]=num; rnd[k]=rand(); return;}
    s[k]++;
    if (v[k]==num)    w[k]++;
    else if (v[k]>num){ insert(ls[k],num); if (rnd[ls[k]]<rnd[k]) rturn(k);}
    else {insert(rs[k],num); if (rnd[rs[k]]<rnd[k]) lturn(k);}
}
void del(int &k,int num)
{
    if (v[k]==num)
    {
        if (w[k]>1) {w[k]--; s[k]--; return;}
        if (ls[k]*rs[k]==0) k=ls[k]+rs[k];
        else if (rnd[ls[k]]<rnd[rs[k]]) {rturn(k); del(k,num);}
        else {lturn(k); del(k,num);}
    }
    else if (v[k]<num) {del(rs[k],num);s[k]--;}
    else {del(ls[k],num);s[k]--;}
}
void build(int k,int l,int r,int pos,int val)
{
    insert(root[k],val);
    int mid=(l+r)>>1;
    if (l==r) return;
    if (pos<=mid)    build(k*2,l,mid,pos,val);
    else build(k*2+1,mid+1,r,pos,val);
}
void change (int k,int l,int r,int pos,int val,int pre)
{
    del(root[k],pre);
    insert(root[k],val);
    if (l==r) return;
    int mid=(l+r)>>1;
    if (pos<=mid) change(k*2,l,mid,pos,val,pre);
    else change(k*2+1,mid+1,r,pos,val,pre);
}
void ask_rank(int k,int num)
{
    if (!k) return;
    if (num==v[k]) {ans+=s[ls[k]]; return;}
    else if (v[k]>num){ask_rank(ls[k],num);}
    else {ans+=s[ls[k]]+w[k]; ask_rank(rs[k],num);}
    
}
void query_rank(int k,int l,int r,int x,int y,int num)
{
    if (l==x && y==r){ask_rank(root[k],num); return;}
    int mid=(l+r)>>1;
    if (y<=mid)    query_rank(k*2,l,mid,x,y,num);
    else if (mid<x)    query_rank(k*2+1,mid+1,r,x,y,num);
    else
    {
        query_rank(k*2,l,mid,x,mid,num);
        query_rank(k*2+1,mid+1,r,mid+1,y,num);    
    } 
}
void query_k(int x,int y,int num)
{
    int l=0,r=inf,tmp;
    while (l<r)
    {
        int mid=(l+r)>>1; ans=1;
        query_rank(1,1,n,x,y,mid);
        if (ans>num)    r=mid;
        else {l=mid+1; tmp=mid;}
    }
    printf("%d\n",tmp);
}

int    main()
{
        memset(root,0,sizeof(root));
        memset(ls,0,sizeof(ls));
        memset(rs,0,sizeof(rs));
        memset(s,0,sizeof(s));
        memset(w,0,sizeof(w));
        sz=0;
        n=read(); m=read();
        for (int i=1; i<=n; i++) a[i]=read();
        for (int i=1; i<=n; i++) build(1,1,n,i,a[i]);
        char ch[10];
        int l,r,k,pos,val;
        for (int i=1; i<=m; i++)
        {
            scanf("%s",ch); 
            if (ch[0]=='Q') {l=read(); r=read(); k=read(); ans=1; query_k(l,r,k);}
            if (ch[0]=='C')    {pos=read(); val=read(); change(1,1,n,pos,val,a[pos]); a[pos]=val;}
        }
    
}
View Code

 

posted @ 2016-05-29 20:31  ACist  阅读(229)  评论(0编辑  收藏  举报