二分+判断,最小值最大(组装电脑,LA 3971)

来源:互联网 发布:mysql批量insert bug 编辑:程序博客网 时间:2024/06/11 19:37

一开始啊,用map和priority_queue搞来搞去,各种upper_bound啊,维护单调啊什么鬼的,编码又麻烦,速度也不快,还WA。

具体就是先把所有的部件都买一个最便宜的,然后放到优先队列里,每次取一个quality最小的,换成一个更大的。因为更大的反而可能更便宜(除了第一次更换一定更贵),所以要维护单调。想效率高点所以用upper_bound。弄了好久都没过,就只好用紫书大白书上的方法,然后又是WA,找不到错,重写了几遍才过。。。


感觉自己好依赖STL,啥都想用STL乱搞,各种迭代器满天飞,编码又复杂,效率又不高,可能入门时做了一道STL的题导致了现在的不良习惯。以后应该多想一点正常的方法,不要过度使用STL。


然后关于这道题,书上说解决“最小值最大”的常用方法是二分答案。确实是以前做过挺多类似的题,就是二分某个最小值,如果可行,那就尝试一个更大的最小值,如果不可行,那就尝试一个更小的最小值。因为二分是O(logn),所以哪怕n很大效率也会很高的。一般是因为不好直接计算最优值,而判断是否可行却很简单,所以用二分。前面也有一道题是枚举加判断的,只不过枚举时总决策很多而可行决策很少。


然后不要盲目的最求效率,这题中n才1000,没有必要为了二分quality而去删改很多,不如直接扫一遍。主要的时间复杂度应该在二分答案上。


代码

#include<bits/stdc++.h>#define maxn 1010using namespace std;typedef pair<int,int> pii;int n,b;map<string,int>id;vector<pii>vec[maxn];int tot;bool ok(int val){    int sum=0;    for(int i=1;i<=tot;i++)    {        int temp=1e9+1;        for(unsigned int j=0;j<vec[i].size();j++)            if(vec[i][j].second>=val) temp=min(temp,vec[i][j].first);        if(temp==1e9+1) return false;        sum+=temp;        if(sum>b) return false;    }    return true;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        tot=0;        id.clear();        scanf("%d %d",&n,&b);        string s;        int x,y;        int l,r;        l=r=0;        for(int i=1;i<=n;i++)        {            cin>>s;            if(!id[s])            {                id[s]=++tot;                vec[tot].clear();            }            int ID=id[s];            cin>>s>>x>>y;            r=max(r,y);            vec[ID].push_back(make_pair(x,y));        }        r++;        while(l<r)        {            int m=l+(r-l)/2;            if(ok(m)) l=m+1;            else r=m;        }        printf("%d\n",l-1);    }    return 0;}


0 0
原创粉丝点击