zzulioj 1536: 小明的序列 (树状数组)

这篇博客介绍了如何解决一个关于序列操作的问题,其中包含两种操作:删除数字和查询数字的排名。给定一个序列,确保所有数字都不相同,博客作者利用树状数组(BIT)来实现高效的操作,包括维护序列状态和回答查询。输入和输出格式以及样例数据也进行了说明。通过使用哈希表进行查找,可以达到O(1)的时间复杂度,而使用map则为O(logn)。快读和手写哈希能进一步提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接 

题目描述

小明获得了一个序列,这个序列内任意两个数字都不一样。现在有 2 种操作,分别是:  
(1) 删除数字 x。  
(2) 询问数字 x 在序列里面排在第几位。 

输入

第一行两个整数 n,m(1≤n,m≤105)。表示序列的长度和操作数量。 
第二行 n个互不相同的正整数,表示最初序列的状态。 
接下来 m行每行两个整数 q,x,q=1表示删除操作,q=2 表示询问操作。

输出

对于每个询问操作,输出一行一个整数表示答案。

样例输入 Copy

3 2
99 88 123
1 88
2 123

样例输出 Copy

2

提示

对于 30% 的数据,满足 1≤n,m≤2000。  
对于 100%的数据,满足 1≤n,m≤105。 

 对于序列中的每个数,map标记一下当前数的下标,并且更新 update(x,1) 删除的话 update(x,-1)

对于询问操作,直接query求前缀和即可得到当前数字在第几个

我这里用的hash_table  查找更快,理论复杂度O1   map的查找复杂度是O logn

#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const int maxn=1e5+5;
int n,m;
int c[maxn];
gp_hash_table<ll,int>mp;
int lowbit(int x)
{
    return x&(-x);
}
void update(int i,int val)
{
    while(i<=maxn)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
int query(int i)
{
    int res=0;
    while(i>0)
    {
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}
int main()
{
    scanf("%d%d",&n,&m);int p;
    for(int i=1;i<=n;i++) scanf("%d",&p),mp[p]=i,update(i,1);
    while(m--)
    {
        int x,y;scanf("%d%d",&x,&y);
        if(x==1) update(mp[y],-1);
        if(x==2)
        {
            printf("%d\n",query(mp[y]));
        }
    }
    return 0;
}

快读+手写hash     更快一点

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
    //fread->read
    bool IOerror=0;
//	inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
    inline char nc(){
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
        if(p1==pend){
            p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
            if(pend==p1){IOerror=1;return -1;}
        }
        return *p1++;
    }
    inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
    template<class T> inline bool read(T &x){
        bool sign=0;char ch=nc();x=0;
        for(;blank(ch);ch=nc());
        if(IOerror)return false;
        if(ch=='-')sign=1,ch=nc();
        for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
        if(sign)x=-x;
        return true;
    }
    inline bool read(double &x){
        bool sign=0;char ch=nc();x=0;
        for(;blank(ch);ch=nc());
        if(IOerror)return false;
        if(ch=='-')sign=1,ch=nc();
        for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
        if(ch=='.'){
            double tmp=1; ch=nc();
            for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
        }
        if(sign)x=-x;
        return true;
    }
    inline bool read(char *s){
        char ch=nc();
        for(;blank(ch);ch=nc());
        if(IOerror)return false;
        for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
        *s=0;
        return true;
    }
    inline bool read(char &c){
        for(c=nc();blank(c);c=nc());
        if(IOerror){c=-1;return false;}
        return true;
    }
    template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
    //fwrite->print
    struct Ostream_fwrite{
        char *buf,*p1,*pend;
        Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
//		void out(char ch){putchar(ch);}
        void out(char ch){if(p1==pend){fwrite(buf,1,BUF_SIZE,stdout);p1=buf;}*p1++=ch;}
        template<class T>void print(T x){
            static char s[33],*s1;s1=s;
            if(!x)*s1++='0';if(x<0)out('-'),x=-x;
            while(x)*s1++=x%10+'0',x/=10;
            while(s1--!=s)out(*s1);
        }
        void print(double x,int y){
            static ll mul[]=
                    {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,
                     10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
                     100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
            if(x<-1e-12)out('-'),x=-x;
            ll x2=(ll)floor(x);if(!y&&x-x2>=0.5)++x2;x-=x2;x*=mul[y];
            ll x3=(ll)floor(x);if(y&&x-x3>=0.5)++x3;print(x2);
            if(y>0){out('.');for(size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i)print(x3);}
        }
        void print(char *s){while(*s)out(*s++);}
        void print(const char *s){while(*s)out(*s++);}
        void flush(){if(p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
        ~Ostream_fwrite(){flush();}
    }Ostream;
    template<class T>void print(T x){Ostream.print(x);}
    inline void print(char x){Ostream.out(x);}
    inline void print(char *s){Ostream.print(s);}
    inline void print(string s){Ostream.print(s.c_str());}
    inline void print(const char *s){Ostream.print(s);}
    inline void print(double x,int y){Ostream.print(x,y);}
    template<class T,class... U>void print(const T& h,const U&... t){print(h);print(t...);}
    void println(){print('\n');}
    template<class T,class... U>void println(const T& h,const U&... t){print(h);println(t...);}
    inline void flush(){Ostream.flush();}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
int n,m;
int c[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int i,int val)
{
    while(i<=maxn)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
int query(int i)
{
    int res=0;
    while(i>0)
    {
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}
struct HashMap //拉链法hash表
{
    static const int MXSZ = 1e5 + 20; //元素总数 查询也会创建元素 能开大就开大
    static const int MOD = 1e5 + 3; //1e3+9 1e4+7 1e6+3 1e7+19 1e8+7
    struct node
    {
        int key;
        int val, nxt;
    }elem[MXSZ];
    int head[MOD], tot;
    void Init() //注意初始化!!!
    {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    int& operator [] (int key)
    {
        int k = key % MOD; //取模位置
        for (int i = head[k]; ~i; i = elem[i].nxt)
            if (elem[i].key == key) //key相等
                return elem[i].val; //返回val引用
        elem[tot].key = key, elem[tot].nxt = head[k], head[k] = tot; //新建项 将原有的接在当前后并记录当前
        return elem[tot++].val = 0; //清空值并返回引用
    }
}mp;
int main()
{
    mp.Init();
    read(n);read(m);int p;
    for(int i=1;i<=n;i++) read(p),mp[p]=i,update(i,1);
    while(m--)
    {
        int x,y;read(x);read(y);
        int z = mp[y];
        if(x==1) update(z,-1);
        if(x==2)
        {
            printf("%d\n",query(z));
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值