cf 420b Online Meeting(前缀和)

传送门:http://codeforces.com/problemset/problem/420/B
题目大意:有n个人m个登入/登出,如果一个人在其他所有人登入期间都是登入状态,那么这个人就是领导,给出一部分的记录,问有那些人可能是领导。
思路:change数组记录登入/登出,登入记为1,登出记为-1,talking记录change的前缀和即为此时登入状态的人数,如果某个时刻有人登出,talking记录的是他登出后的情况,把没有登入但是先出现登出的人在change[0]记录登入,有登入没登出的人在change[m+1]记录登出。因为每个时刻只有一个人登入/登出,所以在m个操作中出现的人的登入的区间只有包含,相交,不想交的关系,不存在相等的关系,所以最多只有一个人可以当领导。
代码:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll M=1e5+10;
ll n,m;
bool leader[M];
ll vis[M];
typedef pair<char,ll> P;
ll id[M];
ll talking[M],change[M];
int main(){
	scanf("%lld%lld",&n,&m);
	fill(leader+1,leader+1+n,1);
	for(ll i=1;i<=m;i++){
		char o;
		ll num;
		cin>>o>>num;
		id[i]=num;
		if(o=='-' && vis[num]==0)
			change[0]++,change[i]--;
		else if(o=='-')
			change[i]--,vis[num]=0;
		else
			change[i]++,vis[num]=i;
	}
	for(ll i=1;i<=n;i++)
		if(vis[i])
			change[m+1]--;
	talking[0]=change[0];
	for(ll i=0;i<=m+1;i++)
		talking[i]=talking[i-1]+change[i];
	ll _id=0;
	bool ok=1;
	for(ll i=1;i<=m;i++){
		if(talking[i]>1 || (change[i]==-1 && talking[i]>0)){//登入的人数大于1时,在这个位子操作的人一定不是领导,在这个位置登出时特殊处理
			leader[id[i]]=0;
		}
		else{
			if(!_id)
				_id=id[i];
			else if(_id!=id[i]){//出现过的id只有一个能当领导,如果出现不相交的情况,会变成有两个人能当领导,如+1,-1,+2,-2,就说明出现过的人没人能当领导
				ok=0;
				break;
			}
		}
	}
	if(!ok){
		for(ll i=1;i<=m;i++)
			leader[id[i]]=0;
	}
	ll ans=0;
	for(ll i=1;i<=n;i++)
		ans+=(leader[i]);
	printf("%lld\n",ans);
	for(ll i=1;i<=n;i++)
		if(leader[i])
			printf("%lld ",i);
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值