题目描述
小明获得了一个序列,这个序列内任意两个数字都不一样。现在有 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;
}