@lawk97
2017-04-20T00:24:02.000000Z
字数 4688
阅读 1144
STL
POJ - 2010
- 题意
奶牛大学招生啦。有C只奶牛申请,会录取N只(N为奇数)。每只奶牛上学需要不同数额的赞助,而学校可以用于赞助奶牛学生的总经费为F。在学校经费的限制下,要使录取的N只奶牛TA们的成绩中位数尽可能高,求出这中位数的可能最大值。
- 思路
首先将奶牛按成绩高低排序。
因为要录取N只奶牛,所以成绩是中位数的奶牛在所有奶牛中的次序必然在[N/2+1,C-N/2]之间取值。在TA前面的奶牛和在TA后面的奶牛,各录取需赞助少的N/2只。如果TA所需的赞助加上其他奶牛需要的赞助之和,小于等于总经费F,则说明这只奶牛的成绩可以作为中位数。
在可作为“中间奶牛”的奶牛中,取成绩的最高的那个。
使用优先队列,便于找到当前奶牛前面和后面的,需赞助少的N/2只。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int n,c,f;
int ans=-1;
int lef[100005],rig[100005];
struct student
{
int score,cost;
}cow[100005];
priority_queue<int>q1,q2;
int cmp(student a,student b)
{
return a.score<b.score;
}
int main()
{
scanf("%d%d%d",&n,&c,&f);
for(int i=0;i<c;i++)
scanf("%d%d",&cow[i].score,&cow[i].cost);
sort(cow, cow+c, cmp);
int l=n/2,r=c-n/2-1;
int sum1=0,sum2=0;
for(int i=0;i<l;i++)
{
sum1+=cow[i].cost;
q1.push(cow[i].cost);
}
for(int i=l;i<=r;i++)
{
lef[i]=sum1;
q1.push(cow[i].cost);
int top=q1.top();
sum1+=cow[i].cost-top;
q1.pop();
}
for(int i=c-1;i>r;i--)
{
sum2+=cow[i].cost;
q2.push(cow[i].cost);
}
for(int i=r;i>=l;i--)
{
rig[i]=sum2;
q2.push(cow[i].cost);
int top=q2.top();
sum2+=cow[i].cost-top;
q2.pop();
}
for(int i=r;i>=l;i--)
{
if(cow[i].cost+lef[i]+rig[i]<=f)
{
ans=cow[i].score;
break;
}
}
printf("%d\n",ans);
return 0;
}
CodeForces - 732E
- 题意
有n台电脑,m个插座,若电脑与插座电压相同,则可以将其连接并正常使用该电脑。也可将插座与适配器相连,转化为一个电压为原值一半(向上取整)的新插座。已知适配器数量充足。
求最多有多少台电脑可用,若有多种方案,以适配器使用量最少的一种为优。
- 思路
电源的电压只能降低,不能升高。
若一个电源的电压,既可以适配一个需电压大的电脑,又可以适配一个需电压小的电脑,那么使他适配需电压大的电脑,既可以保证尽可能多的电脑被供能(贪心),又可以减少适配器的使用。
所需电压比各种电源的供电压最大值还大的电脑,一定不能使用。
所供电压比各种电脑的需电压最大值还大的电源,如果不用适配器,肯定不可以接任何电脑。
因此,可将电源和电脑分别按电压从大到小排序,进行比对。因为电源电压可以变化,且我们需要尽可能控制适配器的使用,所以使用优先队列来放置电源。放置电源的优先队列中,电压高的优先,电压相等的电源所用适配器少的优先。
具体思路如下程序。
- 代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <stack>
#include <queue>
using namespace std;
int n,m,use=0,sum=0;
struct sw{
int id,vol,num;
friend bool operator <(sw a ,sw b){//优先队列默认队头元素最大
if(a.vol!=b.vol)
return a.vol<b.vol;
return a.num>b.num;
}
}s[200005];
struct cu{
int id,vol,ans;
}c[200005];
priority_queue<sw> pq;
int cmp_id(cu a,cu b){
return a.id<b.id;
}
int cmp_v(cu a ,cu b){
return a.vol>b.vol;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&c[i].vol);
c[i].id=i+1;
c[i].ans=0;
}
for(int i=0;i<m;i++){
sw si;
scanf("%d",&s[i].vol);
s[i].id=i+1;
s[i].num=0;
pq.push(s[i]);
}
sort(c,c+n,cmp_v);
for(int i=0;i<n;i++){
if (pq.empty())
{
break;
}
sw f=pq.top();
if(f.vol==c[i].vol){
pq.pop();
c[i].ans=f.id;
s[f.id-1]=f;
sum+=f.num;
use++;
}else if(f.vol>c[i].vol){
pq.pop();
f.num++;
f.vol=ceil(1.0*f.vol/2);
pq.push(f);
i--;
}
}
sort(c,c+n,cmp_id);
printf("%d %d\n",use,sum );
for(int i=0;i<m;i++){
if (i!=0)
{
printf(" ");
}
printf("%d",s[i].num );
}
printf("\n");
for(int i=0;i<n;i++){
if (i!=0)
{
printf(" ");
}
printf("%d",c[i].ans );
}
printf("\n");
return 0;
}
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define INF 1000005
int n,dir,num,minx,now,ans;
int used[155],sl[155],gra[155][155];
string be,st;
map<string,int> m;
int main(){
while(~scanf("%d",&n)&&n!=-1){
cin>>be>>st;
num=1;
minx=INF;
ans=INF;
m.clear();
memset(sl,0,sizeof(sl));
memset(used,0,sizeof(used));
for (int i = 0; i < 155; ++i)
{
for (int j = 0; j < 155; ++j)
{
gra[i][j]=INF;
if (i==j)
{
gra[i][j]=0;
}
}
}
m[be]=num++;
m[st]=num++;
if (be==st)
{
ans=0;
/*
must do it to stop the program,
because there are a wrong m[be]=2
*/
}
for(int i=0;i<n;i++){
cin>>be>>st;
scanf("%d",&dir);//opertion 'cin' spend too much time
if(m[be]==0){
m[be]=num++;
}
if(m[st]==0){
m[st]=num++;
}
gra[m[be]][m[st]]=dir;
gra[m[st]][m[be]]=dir;//no direction
}
if (ans==0)
{
printf("%d\n",ans );
continue;
}
for(int i=1;i<num;i++){
sl[i]=gra[1][i];
}
used[1]=1;
now=1;
//now must have initial value,if the begin point can't connect to others,
for (int i = 2; i < num; ++i)
{
minx=INF;
for(int j=1;j<num;j++){
if (!used[j]&&sl[j]<minx)
{
now=j;
minx=sl[j];
}
}
used[now]=1;
for (int j = 1; j < num; ++j)
{
if (!used[j]&&sl[now]+gra[now][j]<sl[j])
{
sl[j]=sl[now]+gra[now][j];
}
}
}
if (sl[2]<INF)
{
printf("%d\n",sl[2] );
}else{
printf("-1\n");
}
}
return 0;
}
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
int n,l,r,num,flag;
int anl[300005],anr[300005];
map<int,int> p;
int main(){
scanf("%d",&n);
l=1;
r=2;
num=0;
flag=0;
for(int i=1;i<=n;i++){
int now;
scanf("%d",&now);
if (!flag&&p[now]>0) {
r=i;
flag=1;
}
if(flag&&p[now]>r){
anl[num]=l;
anr[num]=r;
num++;
l=r+1;
r=i;
}
if (i==n) {
anl[num]=l;
anr[num]=n;
num++;
}
p[now]=i;
}
if (flag) {
printf("%d\n",num);
for (int i=0; i<num; i++) {
printf("%d %d\n",anl[i],anr[i]);
}
}else{
printf("-1\n");
}
}