嘘~ 正在从服务器偷取页面 . . .

洛谷U187024 Cell Membrane 题解


洛谷U187024 Cell Membrane 题解

题目链接:U187024 Cell Membrane

本题为私题,作者 q779 (没错,就是本人!

题目背景

细胞就像一座化工厂,各个车间(细胞器)有条不紊,忙忙碌碌地生产着各种各样的化学物质,在领导细胞核同志的调控下,共同为化工厂的未来奋斗

工厂人员(化学物质)流动十分频繁,为了保证“工厂“的安全运作,工厂请了一位保安,叫细胞膜

他的日常工作就是检查每一位进出工厂的人

今天他生病了,所以想请你帮帮忙

题目描述

保安给了你一张工厂人员名单表,(用于检查每个要进工厂上班的人是否为员工,不是员工则不能进入),每个人有唯一的编号 \(a_i\)正整数

由于员工的流动性,有一些员工会提前下班,一些下班或休息的员工也会回来继续加班

尊敬的领导细胞核同志要来视察,他会询问编号小于 \(x\) 且在上班的人有多少个

为了方便起见,我们可以把这些条件看作 \(m\) 个操作

输入数据将由以下格式给出

  • 1 x 表示编号为x的人想要进入工厂
  • 2 x 表示编号为x的人离开了工厂
  • 3 x 表示询问编号小于x且在上班的人的个数

输入格式

建议使用较快的输入输出。

第一行,给出人员名单表长度 \(n\) 和操作个数 \(m\)

第二行,\(n\) 个数,表示名单表(不保证有序)

接下来 \(m\) 行,给出形如 op x 的操作,详见题目描述

输出格式

对于每个 3 询问,都输出一行表示答案

样例 #1

样例输入 #1

4 5
1 2 3 4
1 5
1 4
1 2
1 3
3 999

样例输出 #1

3

数据范围

对于 \(30\%\) 的数据,保证 \(1\le n,m \le 1000,~1\le a_i \le 10^9\)

对于 \(100\%\) 的数据,保证 \(1\le n,m \le 2\times10^5,~1\le a_i \le 10^9\)

数据保证不在工厂上班的人不会出“工厂”,在工厂上班的人不会进工厂

命题人:q779 验题人:q779

这道题是我高一上学期出的,当时水平很菜只会出点基础题,评级最多普及-。

原来的 std 是维护一个 vector ,每次二分查找正确的位置,删除和修改

但实际上这个复杂度是错误的,因为 vector 的删除操作实际上是 \(\mathcal{O}(n)\) 的。

正解应该是把所有出现过的 \(a_i\) 离散化,然后用树状数组来维护。

时间复杂度 \(\mathcal{O}(n \log n)\)

代码:

// 2024年04月26日 01:02:04
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
typedef pair<int,int> pii;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(4e5 + 15))

int n, m, len, a[N], b[N], o[N], q[N], tr[N]; char ck[N];
int lowbit(int x) { return x & (-x); }
void add(int x, int v) { for(int i = x; i <= len; i += lowbit(i)) tr[i] += v; }
int sum(int x, int r = 0){ for(int i = x; i; i -= lowbit(i)) r += tr[i]; return r; }
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n >> m;
    for(int i = 1; i <= n; i++) { cin >> a[i], b[i] = a[i]; }
    for(int i = 1; i <= m; i++) { cin >> o[i] >> q[i], b[i + n] = q[i]; }
    sort(b + 1, b + 1 + n + m); len = unique(b + 1, b + 1 + n + m) - b - 1;
    for(int i = 1; i <= n; i++) { 
        ck[a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b] = true;
    }
    for(int i = 1; i <= m; i++)
    {
        int x = lower_bound(b + 1, b + 1 + len, q[i]) - b;
        if(o[i] == 1) { if(ck[x]) add(x, 1); }
        else if(o[i] == 2) { if(ck[x]) add(x, -1); }
        else if(o[i] == 3) cout << sum(x - 1) << '\n';
    }
    return 0;
}

如果有人好奇 std 是啥,那我就贴上来

// 2021年10月30日 22:38:54
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define gc() getchar()
#define pc(a) putchar(a)
template<typename T>inline void read(T &k)
{
	char ch=gc();T x=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
	k=x*f;
}
template<typename T>inline void write(T k)
{
	if(k<0){pc('-');k=-k;}
	if(k>9)write(k/10);
	pc(k%10+'0');
}
#define MAXN (int)(2e5+5)
int n,Q;
unordered_map<int,bool>mp,vis;
vector<int> vec;
signed main()
{
	// freopen("3.in","r",stdin);
	// freopen("3.out","w",stdout);
	read(n);read(Q);
	for(int i=1,x; i<=n; i++)
		read(x),mp[x]=1;
	while(Q--)
	{
		int op,x;
		read(op);read(x);
		if(op==1&&mp[x])
		{
			vis[x]=1;
			vec.insert(lower_bound(vec.begin(),vec.end(),x),x);
		}
		if(op==2)
		{
			vis[x]=0;
			vec.erase(lower_bound(vec.begin(),vec.end(),x));
		}
		if(op==3)
		{
			int p=lower_bound(vec.begin(),vec.end(),x)-vec.begin();
			write(p);pc('\n');
		}
	}
	return 0;
}

题外话

虽说当时确实很菜,但我确实很努力。

可以说高一上学期是我高中最痛苦但又最快乐的时候。

痛苦的是平均每天睡眠都不超过4小时,快乐的是有很多有趣的同学。

虽然很多人都不再联系了,但是至少在他们眼中我的印象应该还不错吧。

从那以后,我的高中生活没有过能让我说的上快乐的,甚至没有一天让我感到不痛苦的。

很快又要回到学校了,希望“重生”后的我可以体验更多有趣的事情吧。


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录