Codeforces 1288E Messenger Simulator(BIT)

题目链接:

Codeforces 1288E Messenger Simulator

思路:

1.对于每个数,它的最小要么是被移到最左边是1,要么就是初始位置;
2.至于计算最大,贪心的思想是:如果一个数要被移动,我们在移动之前计算一下这个数左边有多少个;同时所有移动结束后也应该计算一下;最大取所有历史计算值的最大值;
3.如何快速的计算左边有多少个数呢?这种动态前缀和当然是用树状数组,如何模拟往左移的情况呢?我们可以一开始就在bit数组的最左边设m个值为0的点,每次移动就是从右往左填补这m个位置;

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 3e5 + 5;
int n, m, N, a[maxn], bit[maxn << 1];
int mn[maxn], mx[maxn], pos[maxn];
#define lowbit(i) (i&-i)
inline void add(int i, int x){
	while(i <= N) bit[i] += x, i += lowbit(i);	
}
inline int sum(int i){
	int ans = 0;
	while(i) ans += bit[i], i -= lowbit(i);
	return ans;	
}

int main() {
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif	
	scanf("%d %d", &n, &m);
	N = n + m;
	for(int i = 1; i <= m; i++) scanf("%d", a + i);
	for(int i = 1; i <= n; i++){
		mn[i] = mx[i] = i;
		add(i + m, 1);
		pos[i] = i + m;
	}
	for(int i = 1; i <= m; i++){
		int now = a[i];
		mn[now] = 1;
		mx[now] = max(mx[now], sum(pos[now]));
		add(pos[now], -1);
		pos[now] = m - i + 1;
		add(pos[now], 1);
	}
	for(int i = 1; i <= n; i++) mx[i] = max(mx[i], sum(pos[i]));
	for(int i = 1; i <= n; i++) printf("%d %d\n", mn[i], mx[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值