P2464 [SDOI2008] 郁闷的小 J

[SDOI2008] 郁闷的小 J - 洛谷

考虑给每个编号开一个版本,维护区间和,于是想到主席树,N<=1e5 ,离散化即可

注意把操作离线下来的编码也要离散化

#include <bits/stdc++.h>

#define INF (1ll<<60)
#define eps 1e-6
using namespace std;
typedef long long ll;
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef unsigned long long ull;
typedef vector<vector<int> > vii;
typedef vector<vector<vector<int> > > viii;
typedef vector<ll> vl;
typedef vector<vector<ll> > vll;
typedef vector<double> vd;
typedef vector<vector<double> > vdd;
#define time mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());//稳定随机卡牛魔 ull
const int N=1e5+9;
int a[N];
vi X;
int binary(int x){
    return lower_bound(X.begin(),X.end(),x)-X.begin()+1;
}
struct Q{
    char op;
    int l,r,k;
}que[N];
//可持久化线段树
struct KCJSEG{
    struct node{
        int l,r;
        ll val;
    }seg[N<<5];
#define tl(id) seg[id].l
#define tr(id) seg[id].r
#define pushup(id) seg[id].val=seg[tl(id)].val+seg[tr(id)].val
    int root[N],index,mx;
    int inrange(int L,int R,int l,int r){return L>=l && R<=r;}
    int outofrange(int L,int R,int l,int r){return L>r || l>R;}
    void update(int post,int &curr,int l,int r,int pos,int v){
        curr=++index;
        seg[curr]=seg[post];
        if(l==r){
            seg[curr].val+=v;
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=pos){
            update(tl(post),tl(curr),l,mid,pos,v);
        }else{
            update(tr(post),tr(curr),mid+1,r,pos,v);
        }
        pushup(curr);
    }
    void insert(int &id,int l,int r,int pos,int k){
        if(!id){
            id=++index;
        }
        if(l==r){
            seg[id].val+=k;
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=pos){
            insert(tl(id),l,mid,pos,k);
        }else{
            insert(tr(id),mid+1,r,pos,k);
        }
        pushup(id);
    }
    ll query(int curr,int L,int R,int l,int r){
        if(inrange(L,R,l,r)){
            return seg[curr].val;
        }else if(!outofrange(L,R,l,r)){
            int mid=(L+R)>>1;
            return query(tl(curr),L,mid,l,r)+query(tr(curr),mid+1,R,l,r);
        }else{
            return 0;
        }
    }
}t;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        X.push_back(a[i]);
    }
    for(int i=1;i<=m;i++){
        char op;
        cin>>op;
        if(op=='C'){
            int a,p;
            cin>>a>>p;
            que[i]={'C',a,a,p};
            X.push_back(p);
        }else{
            int l,r,k;
            cin>>l>>r>>k;
            que[i]={'Q',l,r,k};
            X.push_back(k);
        }
    }
    sort(X.begin(), X.end());
    X.erase(unique(X.begin(),X.end()),X.end());
    for(int i=1;i<=n;i++){
        a[i]= binary(a[i]);
        t.insert(t.root[a[i]],1,n,i,1);
    }
    for(int i=1;i<=m;i++){
        if(que[i].op=='C'){
            int pos=que[i].l;
            int p=que[i].k;
            p= binary(p);
            t.insert(t.root[a[pos]],1,n,pos,-1);
            a[pos]=p;
            t.insert(t.root[a[pos]],1,n,pos,1);
        }else{
            int id=que[i].k;
            id=binary(id);
            int l=que[i].l;
            int r=que[i].r;
            cout<<t.query(t.root[id],1,n,l,r)<<'\n';
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值