[SDOI2008] 郁闷的小J

题目描述:

雾。

题目分析:

好像是平衡树啊qwq
~~我不管,平衡树辣么长,我才不写呢~~
我们直接对每个树都建一颗位置线段树就行啦,维护每个位置节点上是否有本书。
别忘了离散化~

题目链接:

Luogu 2464

Ac 代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxm=400100; 
namespace seg{
    int rt[maxm],sz;
    int ls[maxm*8],rs[maxm*8],sum[maxm*8];  
    void insert(int &now,int l,int r,int ind,int num)
    {
        if(!now) now=++sz;
        if(l>=r)
        {
            sum[now]+=num;
            return;
        }
        int mid=(l+r)>>1;
        if(ind<=mid) insert(ls[now],l,mid,ind,num);
        else insert(rs[now],mid+1,r,ind,num);
        sum[now]=sum[ls[now]]+sum[rs[now]];
    }
    int ask(int now,int l,int r,int ql,int qr)
    {
        if(!now) return 0;
        if(ql<=l&&r<=qr) return sum[now];
        int mid=(l+r)>>1;
        int res=0;
        if(ql<=mid) res+=ask(ls[now],l,mid,ql,qr);
        if(qr>mid) res+=ask(rs[now],mid+1,r,ql,qr);
        return res;
    }
}
using namespace seg;
struct node{
    int opt,l,r,id;
}q[maxm*4];
int hash[maxm*10],a[maxm],n,m;
int main()
{
    scanf("%d%d",&n,&m);
    int tot=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        hash[++tot]=a[i];
    }
    char s[10];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if(s[0]=='C')
        {
            q[i].opt=0;
            scanf("%d%d",&q[i].l,&q[i].id);
        }
        else
        {
            q[i].opt=1;
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].id);
        }
        hash[++tot]=q[i].id;
    }
    std::sort(hash+1,hash+tot+1);
    int t=std::unique(hash+1,hash+tot+1)-hash-1;
    for(int i=1;i<=n;i++)
    {
        a[i]=std::lower_bound(hash+1,hash+t+1,a[i])-hash;
        insert(rt[a[i]],1,n,i,1);
    }
    for(int i=1;i<=m;i++)
    {
        if(!q[i].opt)
        {
            insert(rt[a[q[i].l]],1,n,q[i].l,-1);
            a[q[i].l]=std::lower_bound(hash+1,hash+t+1,q[i].id)-hash;
            insert(rt[a[q[i].l]],1,n,q[i].l,1);
        }
        else 
        {
            int id=std::lower_bound(hash+1,hash+t+1,q[i].id)-hash;
            printf("%d\n",ask(rt[id],1,n,q[i].l,q[i].r));
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值