Messenger Simulator(树状数组)

题目链接:http://codeforces.com/contest/1288/problem/E
参考:https://www.cnblogs.com/pixel-Teee/p/12203233.html
题意:给定一个初始序列1,2,3…,n.m次操作,每次将 a i ( 1 < = a i < = n ) a_i(1<=a_i<=n) 提到第一位,求整个过程中,每个数出现的最左和左右的位置,并输出。 ( 1 < = n , m < = 3 e 5 ) (1<=n,m<=3e5)
题解:模拟,每次提数,将选中的数向前提,被提到的数,则其最左边是1,最右可以用树状数组前缀和计算。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=300010;

int n,m;
int sum[maxn<<1];
int l[maxn],r[maxn];
int a[maxn],pos[maxn];

int lowbit(int x){
	return x&(-x); 
}
void update(int x,int val){
	for(int i=x;i<(maxn<<1);i+=lowbit(i)){
		sum[i]+=val;
	}
}
int query(int x){
	int res=0;
	for(int i=x;i;i-=lowbit(i))
		res+=sum[i];
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		l[i]=r[i]=i;
		pos[i]=i+m;
		update(i+m,1);
	}
	for(int i=1,x;i<=m;i++){
		scanf("%d",&x);
		l[x]=1;
		r[x]=max(r[x],query(pos[x]));
		update(pos[x],-1);
		pos[x]=m-i+1;
		update(pos[x],1);
	}
	for(int i=1;i<=n;i++){
		r[i]=max(r[i],query(pos[i]));
		printf("%d %d\n",l[i],r[i]);
	}
	return 0;
}
发布了71 篇原创文章 · 获赞 1 · 访问量 2807

猜你喜欢

转载自blog.csdn.net/weixin_43918473/article/details/104114451