1. 程式人生 > >BZOJ4977 跳傘求生(貪心)

BZOJ4977 跳傘求生(貪心)

  如果現在選定了一些要求消滅的敵人而不考慮積分,顯然應該讓每個敵人被剛好能消滅他的人消滅。再考慮最大化積分,顯然我們應該優先消滅ci-bi大的敵人,所選用的a也應儘量大。於是按ci-bi從大到小排序,用一個multiset維護a,每次看其中是否有能消滅該敵人的人,如果有則將最小的刪去,並用選中的Σci-bi及從大到小選ai更新答案。注意按這種方式將所有能消滅的人都消滅並不一定是最優的,比如這組資料。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include
<cstring> #include<algorithm> #include<set> using namespace std; #define ll long long #define N 100010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N]; ll ans,tot; multiset<int> f; struct data { int x,y; bool operator
<(const data&a) const { return y>a.y; } }b[N]; int main() { #ifndef ONLINE_JUDGE freopen("bzoj4977.in","r",stdin); freopen("bzoj4977.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); for (int i=1;i<=n;i++) f.insert(a[i]=read()); sort(a+1,a+n+1),reverse(a+1,a+n+1); for (int i=1;i<=m;i++) b[i].x=read(),b[i].y=read()-b[i].x; sort(b+1,b+m+1); int cnt=0; for (int i=1;i<=m;i++) { multiset<int>::iterator it=f.lower_bound(b[i].x+1); if (it!=f.end()) { ans=max(ans,tot+=a[++cnt]+b[i].y); f.erase(it); } } cout<<ans; return 0; }