ZOJ 2112 Dynamic Rankings 带修主席树(树状数组套主席树

115 篇文章 0 订阅
6 篇文章 0 订阅

ZOJ2112

啥 第一道树套树 

题意 给你n个数 两种操作 一种操作查询L-R 第k大的树 静态主席树经典问题 第二种操作 把a[i] 改为t

做法 我们知道如果你想建主席树 然后暴力维护 暴力跑 时间复杂度讲会是 m*n*logn 就TLE了 况且你建主席树太多还会MLE

那么怎么做到修改呢?首先我们要知道一定要把后来修改的值也放进去离散化的数组里面 然后还是正常建主席树 唯一的区别是 我们考虑改一个值 实际上就是在那个树的那个值上-1 并且新的值+1 这就很像树状数组 然后ul ur数组是随着主席树下移用的 结构体的带修主席树还不会敲 所以和之前的代码有一点点不同 思路大抵相同 看看吧

#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 6e4+5;
const int MAX_M = 1e4+5;
int T[MAX_N],S[MAX_N],L[MAX_N*32],R[MAX_N*32],sum[MAX_N*32];
vector<int > vt;
int getid(int x){return lower_bound(vt.begin(),vt.end(),x)-vt.begin()+1;}
int arr[MAX_N],ul[MAX_N],ur[MAX_N];
int n,m,cnt,num;
struct node{int l,r,k;bool flag;}Q[MAX_M];
void build(int &rt,int l,int r)
{
    rt = ++cnt,sum[rt] = 0;
    if(l==r) return;
    int mid = (l+r)>>1;
    build(L[rt],l,mid);
    build(R[rt],mid+1,r);
}
void update(int l,int r,int &x,int y,int pos,int val)
{
    x = ++cnt,L[x] = L[y],R[x] = R[y],sum[x] = sum[y] + val;
    if(l==r) return ;
    int mid = (l+r)>>1;
    if(pos<=mid) update(l,mid,L[x],L[y],pos,val);
    else update(mid+1,r,R[x],R[y],pos,val);
}
int lowbit(int x){return x&(-x);}
void add(int x,int val)
{
    int res = getid(arr[x]);
    while(x<=n)
    {
        update(1,num,S[x],S[x],res,val);
        x+=lowbit(x);
    }
}
int Sum(int x,bool flag)
{
    int res = 0;
    while(x)
    {
        if(flag) res += sum[L[ur[x]]];
        else res += sum[L[ul[x]]];
        x-=lowbit(x);
    }
    return res;
}
int query(int l,int r,int x,int y,int tx,int ty,int k)
{
    if(l==r) return l;
    int mid = (l+r)>>1;
    int res = Sum(y,true) - Sum(x,false) + sum[L[ty]] - sum[L[tx]];
    if(k<=res)
    {
        for(int i = y;i;i-=lowbit(i)) ur[i] = L[ur[i]];
        for(int i = x;i;i-=lowbit(i)) ul[i] = L[ul[i]];
        return query(l,mid,x,y,L[tx],L[ty],k);
    }
    else
    {
        for(int i = y;i;i-=lowbit(i)) ur[i] = R[ur[i]];
        for(int i = x;i;i-=lowbit(i)) ul[i] = R[ul[i]];
        return query(mid+1,r,x,y,R[tx],R[ty],k-res);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        vector<int > vt_;
        swap(vt,vt_);
        char str[5];
        num = 0;
        scanf("%d%d",&n,&m);
        for(int i = 1;i<=n;++i) scanf("%d",&arr[i]),vt.push_back(arr[i]);
        for(int i = 1;i<=m;++i)
        {
            scanf("%s",str);
            if(str[0]=='Q')
            {
                scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].k);
                Q[i].flag = true;
            }
            else
            {
                scanf("%d%d",&Q[i].l,&Q[i].r);
                Q[i].flag = false;
                vt.push_back(Q[i].r);
            }
        }
        sort(vt.begin(),vt.end()),vt.erase(unique(vt.begin(),vt.end()),vt.end());
        int tmp = vt.size();
        num = tmp;
        cnt = 0;
        build(T[0],1,num);
        for(int i = 1;i<=n;++i) update(1,num,T[i],T[i-1],getid(arr[i]),1);
        for(int i = 1;i<=n;++i) S[i]  = T[0];
        for(int i = 1;i<=m;++i)
        {
            if(Q[i].flag)
            {
                for(int j = Q[i].r;j;j-=lowbit(j)) ur[j] = S[j];
                for(int j = Q[i].l-1;j;j-=lowbit(j)) ul[j] = S[j];
                printf("%d\n",vt[query(1,num,Q[i].l-1,Q[i].r,T[Q[i].l-1],T[Q[i].r],Q[i].k)-1]);
            }
            else
            {
                add(Q[i].l,-1);
                arr[Q[i].l] = Q[i].r;
                add(Q[i].l,1);
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值