bzoj4977 跳伞求生——贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4977
今天讲的贪心题,真神奇啊;
首先,要得到尽量多选队友的解;
把队友按 a[i] 从小到大排序,敌人按 b[i] 从小到大排序,然后对于每个队友,选择能攻击的、收益最多的敌人;
如果没有能攻击的敌人,就把之前最小的一个队友踢掉代替,能使答案更优;
但尽量多选队友不一定是最终的最优答案,因为有些价值很小(为负)的敌人不如不选;
所以需要调整,很妙的做法,就是直接踢掉最小的队友和收益最小的敌人,那么剩下的队友和敌人也一定可以配对,过程中取最优解;
于是去写了,然而秒WA,自己码力好弱啊,打击...
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; int const maxn=1e5+5,inf=1e9; int n,m,a[maxn]; ll ans; bool vis[maxn],out[maxn]; struct N{ int b,c,bh; bool operator < (const N &y) const { return c-b<y.c-y.b;//priority_queue大根堆 } }p[maxn],t[maxn]; priority_queue<N>qen; priority_queue<int>q2; priority_queue<int>q; bool cmp(N x,N y){return x.b<y.b;} int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++)scanf("%d%d",&p[i].b,&p[i].c); sort(a+1,a+n+1); sort(p+1,p+m+1,cmp); for(int i=1;i<=m;i++)p[i].bh=i; int j=1,pr=1; for(int i=1;i<=n;i++) { while(p[j].b<=a[i]) {qen.push(p[j]); j++;} if(!qen.size()) {t[i]=t[pr]; out[pr]=1; pr++;} else {t[i]=qen.top(); vis[t[i].bh]=1; qen.pop();} } for(int i=1;i<=n;i++) if(!out[i])ans+=a[i]-t[i].b+t[i].c; for(int i=1;i<=m;i++) if(vis[i])q2.push(p[i].b-p[i].c); for(int i=1;i<=n;i++) if(!out[i])q.push(-a[i]);// ll tmp=ans; while(q.size()&&q2.size()) { int x=-q.top(); q.pop(); int y=-q2.top(); q2.pop(); tmp-=x; tmp-=y; ans=max(ans,tmp); } printf("%lld\n",ans); return 0; }
看看人家写的简洁优美AC代码:https://blog.csdn.net/dream_lolita/article/details/79302382
然后就模仿着写了;练习码力...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; int const maxn=1e5+5; int n,m,w[maxn],hd,tl; ll ans,sum; struct N{ int x,y; bool tp; bool operator < (const N &b) const { if(x==b.x)return tp<b.tp; else return x<b.x; } N(int x=0,int y=0,bool t=0):x(x),y(y),tp(t) {} }t[maxn<<1]; priority_queue<int>q; priority_queue<int,vector<int>,greater<int> >p; int main() { scanf("%d%d",&n,&m); for(int i=1,x;i<=n;i++)scanf("%d",&t[i].x); for(int i=1,x,y;i<=m;i++) { n++; scanf("%d%d",&x,&y); t[n]=N(x,y-x,1); } sort(t+1,t+n+1); hd=1; for(int i=1;i<=n;i++) { if(t[i].tp)q.push(t[i].y); else { if(!q.size()) { if(hd<=tl) { int tmp=w[hd]; hd++; sum+=t[i].x-tmp; w[++tl]=t[i].x; } } else { int tmp=q.top(); q.pop(); sum+=t[i].x+tmp; p.push(tmp);//tmp被使用过 w[++tl]=t[i].x; } } } ans=sum; for(int i=hd;i<=tl;i++) { sum-=w[i]+p.top(); p.pop(); ans=max(ans,sum); } printf("%lld\n",ans); return 0; }