二分

1. poj 1759

题意还是需要看原题,不好描述。

实际上这个题只需要注意一点,就是把关系式改成递推式,然后就可以发现第二项完全决定了后面的位置,所以二分第二项的高度即可。

import java.util.*;
import java.io.*;
import java.math.*;

public class Main {
    public static final int maxv = 200005;
    public static final int shift = 100000;
    static int N;
    static double A;

    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(new File(
                "/home/develop/eclipse_file/ACMproject/src/in"));
        // Scanner in=new Scanner(System.in);
        N=in.nextInt();
        A=in.nextDouble();
        double l=A,r=0;
        double ansl=1e10,ansl2=0;
        while(Math.abs(ansl-ansl2)>0.001){
            double mid=(l+r)/2;
            double res=check(mid);
            if(res>0){
                l=mid;
                ansl2=ansl;
                ansl=res;
            }else{
                r=mid;
            }
        }
        System.out.printf("%.2f\n",ansl);
        in.close();
    }
    static double check(double a2){
        double now=0;
        double a1=A;
        int i;
        for(i=3;i<=N;i++){
            now=2*a2-a1+2;
            a1=a2;
            a2=now;
            if(now<0) return -1;
        }
        return now;
    }
}
View Code

 2. poj 3104

题目:有n件湿衣服和一个烘干机,烘干机里同时只能放一件衣服,问最小时间.

思路:最小时间肯定是从湿度最大的开始烘,然后二分即可.

/*
* @author:  Cwind
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-10)
#define INF (1000000300)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=1e5+300;
int n,k;
int a[maxn];
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    scanf("%d",&k);
    sort(a,a+n,greater<int>());
    if(k==1){
        printf("%d\n",a[0]);
        return 0;
    }
    int l=0,r=1e9+1;
    while(r-l>1){
        int mid=(l+r)>>1;
        int t=mid;
        bool f=1;
        for(int i=0;i<n;i++){
            if(a[i]-(mid-t)<=t) break;
            int x=(a[i]-(mid-t)-t+k-2)/(k-1);
            if(x<=t) t-=x;
            else{
                f=0;
                break;
            }
        }
        if(f) r=mid;
        else l=mid;
    }
    printf("%d\n",r);
    return 0;    
}
View Code

 3. poj 3111

题目:每个物品有重量和价值,最大化k个物品的单位重量的平均价值.

思路:设出平均价值然后二分,实际上这就是一个裸的01分数规划.

/*
* @author:  Cwind
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define INF (1000000300)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=1e5+300;
double m;
int n,k;
struct any{
    int x,y,id;
    bool operator < (const any &C)const{
        return x-m*y>C.x-m*C.y;
    }
}a[maxn];
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].id=i+1;
    }
    double l=0,r=1e12;
    while(r-l>eps){
        double mid=(r+l)/2;
        m=mid;
        sort(a,a+n);
        double sum=0;
        for(int i=0;i<k;i++){
            sum+=a[i].x-mid*a[i].y;
            if(sum<0) break;
        }
        if(sum<0) r=mid;
        else l=mid;
    }
    for(int i=0;i<k;i++){
        printf("%d ",a[i].id);
    }
    return 0;    
}
View Code

 4. poj 3484

题目:以首项,公差,最大值给出若干等差数列,保证只有一个数出现了奇数次,问是哪个数.

思路:到某个位置所有数字出现次数的总和,可以发现在那个数后面的总和肯定是奇数,前面的是偶数,就可以二分了....这题输入比较蛋疼,不过学习了一个新的姿势..

/*
* @author:  Cwind
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define INF (1000000300)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

struct data{
    ll x,y,z;
    data(ll x,ll y,ll z):x(x),y(y),z(z){}
};
ll toll(const string &s){
    int len=s.length();
    ll ans=0;
    for(int i=0;i<len&&!isspace(s[i]);i++){
        ans=ans*10+s[i]-'0';
    }
    return ans;
}
vector<data> d;
ll count(ll mid){
    ll sum=0;
    for(int i=0;i<d.size();i++){
        if(mid<d[i].x) continue;
        sum+=((min(mid,d[i].y)-d[i].x)/d[i].z+1);
    }
    return sum;
}
string r;
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    while(!cin.eof()){
        d.clear();
        getline(cin,r);
        if(r.empty()||!isdigit(r[0])) continue;
        do{
            ll a,b,c;
            sscanf(r.c_str(),"%lld%lld%lld",&a,&b,&c);
            d.pb(data(a,b,c));
            if(cin.eof()) break;
            getline(cin,r);
            if(r.empty()||!isdigit(r[0])) break;
        }while(1);
        ll l=0,r=1e11;
        while(r-l>1){
            ll mid=(r+l)>>1;
            int sum=count(mid);
            if(sum%2==0) l=mid;
            else r=mid;
        }
        if(r>1e10){
            puts("no corruption");
        }else{
            printf("%lld %lld\n",r,count(r)-count(r-1));
        }
    }
    return 0;    
}
View Code

 5. 二分第k大

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define INF (1000000300)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=1e6+300;
int n,k;
int a[maxn];
int b[maxn];
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    cin>>n>>k;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    if(k<=0||k>n){
        puts("-1");
        return 0;
    }
    int l=0,r=n-1;
    int ans=0;
    while(k>0){
        int mid=(l+r)>>1;
        int x=a[mid];
        int ll=l,rr=r;
        for(int i=l;i<=r;i++){
            if(a[i]==x) continue;
            if(a[i]>x) b[rr--]=a[i];
            else b[ll++]=a[i];
        }
        b[ll++]=x;
        if(ll-l==k){
            ans=x;
            break;
        }else if(ll-l>k){
            r=rr;
        }else{
            k-=ll-l;
            l=ll;
        }
        for(int i=l;i<=r;i++)
            a[i]=b[i];
    }
    cout<<ans<<endl;
    return 0;    
}
View Code

 

posted @ 2015-06-18 18:44  PlusSeven  阅读(193)  评论(0编辑  收藏  举报