二分
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; } }
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; }
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; }
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; }
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; }