Codeforces Round #652 (Div. 2) E - DeadLee (贪心)

题目链接
思路:
把n个食物的需求need求出来。
每次都选择一个 a[i]-need[i] 最大的食物i
如果这个是非负的 就可以,否则必死。。
那么把喜欢的食物包含i的这批人 放在最后 ,无论前面的人怎么放 这些都是合法的。
然后把这批人喜欢的另一个食物的需求减减。
一直执行这个过程,直到m个人都搞完。
所有过程可以用线段树完成(全局最大值查询,单点更新)
最后倒序输出即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int n,m,a[N],L[N],R[N],dx[N];
#define mid (l+r>>1)
#define ls o<<1
#define rs o<<1|1
int t[N<<2];
vector<int>v[N];
void build(int o,int l,int r){
	if(l==r){
		t[o]=a[l]-dx[l];
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	t[o]=max(t[ls],t[rs]);
}
int get(int o,int l,int r){
	if(l==r)return l;
	if(t[ls]>t[rs])return get(ls,l,mid);
	return get(rs,mid+1,r);
}
void up(int o,int l,int r,int x,int d){
	if(l==r){
		t[o]+=d;
		return ;
	}
	if(x<=mid)up(ls,l,mid,x,d);
	else up(rs,mid+1,r,x,d);
	t[o]=max(t[ls],t[rs]);
}
int vis[N];
int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
  for(int i=1;i<=n;i++)cin>>a[i];
  for(int i=1;i<=m;i++){
  	cin>>L[i]>>R[i];
  	v[L[i]].pb(i);
  	v[R[i]].pb(i);
  	dx[L[i]]++;
  	dx[R[i]]++;
  }
  build(1,1,n);
  vector<int>ans;
  while(ans.size()<m){
  	int now=get(1,1,n);
  	if(dx[now]>a[now])return cout<<"DEAD\n",0;
  	up(1,1,n,now,-1e9);
  	for(auto k:v[now]){
  		if(vis[k])continue;
  		ans.pb(k);
  		vis[k]=1;
  		if(L[k]!=now)up(1,1,n,L[k],1),dx[L[k]]--;
  		else up(1,1,n,R[k],1),dx[R[k]]--;
  	}
  }
  cout<<"ALIVE\n";
  reverse(ans.begin(),ans.end());
  for(auto k:ans)cout<<k<<' ';
 	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40655981/article/details/106941016