最大化最小值
POJ 3258: River Hopscotch
同noip跳石头。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
同noip跳石头。
*/
#include
#include
#include
#include
#include
#include
POJ 3273: Monthly Expense
最小化最大值。
从左往右check即可。预处理前缀和简化运算。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
最小化最大值。
从左往右check即可。预处理前缀和简化运算。
*/
#include
#include
#include
#include
#include
#include
POJ 3104: Drying
不开long long会WA(原因未知),用了cin会TLE。(这两个坑坑了了我五六次提交)
剩下就很简单了,二分时间然后check吹风机使用的总时间是否<=mid即可。
具体地说,对于二分值mid,如果衣服i的含水量<=mid,则不用操作。
如果衣服i的含水量>mid,则设吹风机对衣服i吹了x秒。
则x满足不等式kx+(mid-x)>=a[i],即x>=(a[i]-mid)/(k-1)。
也就是说,对于衣服i,需要吹ceil((a[i]-mid)/(k-1))秒。
ps:注意这里k-1可能为0,所以要特判k=1的情况。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
不开long long会WA(原因未知),用了cin会TLE。(这两个坑坑了了我五六次提交)
剩下就很简单了,二分时间然后check吹风机使用的总时间是否<=mid即可。
具体地说,对于二分值mid,如果衣服i的含水量<=mid,则不用操作。
如果衣服i的含水量>mid,则设吹风机对衣服i吹了x秒。
则x满足不等式kx+(mid-x)>=a[i],即x>=(a[i]-mid)/(k-1)。
也就是说,对于衣服i,需要吹ceil((a[i]-mid)/(k-1))秒。
ps:注意这里k-1可能为0,所以要特判k=1的情况。
*/
#include
#include
#include
#include
#include
#include
POJ 3045: Cow Acrobats
题解链接 https://www.cnblogs.com/wmrv587/p/3700452.html
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
https://www.cnblogs.com/wmrv587/p/3700452.html
*/
#include
#include
#include
#include
#include
#include
01分数规划
POJ 2976: Dropping tests
设答案为mid,二分答案。
具体check过程如下:
,则
即,只要对排序后,取较大的n-k个,判断和是否大于等于0即可。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
设答案为mid,二分答案。
具体check过程如下:
∑ai/∑bi>=mid,则∑ai-mid*∑bi>=0
即∑(ai-mid*bi)>=0,只要对ai-mid*bi排序后,取较大的n-k个,判断和是否大于等于0即可。
*/
#include
#include
#include
#include
#include
#include
POJ 3111: K Best
方法同Dropping tests。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
方法同Dropping tests。
*/
#include
#include
#include
#include
#include
#include
第k大值
POJ 3579: Median
二分答案,然后用upper_bound来求绝对值差在mid以内的数对的个数即可。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
二分答案,然后用upper_bound来求绝对值差在mid以内的数对的个数即可。
*/
#include
#include
#include
#include
#include
#include
POJ 3685: Matrix
观察这个式子,可以发现j不变的情况下,随着i的增大,Aij也相应增大。
由这个受到启发:二分枚举第M小的数,然后按列寻找,找到第一个大于这个数的位置,就可以知道该列中有多少个数是大于这个数。
难点是二分范围和精度问题,因为用int结果WA无数次,最后一个个换掉,最后全部变成long long才过。
代码如下
/*
*/
#define method_2
#ifdef method_1
/*
打表用
*/
#include
#include
#include
#include
#include
#include
最小化第k大值
POJ 2010: Moo University - Financial Aid
题解链接 https://www.jianshu.com/p/5765513ce5b4
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
将所有奶牛按照score升序排序后,从大向小一次尝试作为中位数是否可行即可。
为了提高对于每头奶牛判断的效率,用sum1[i]表示i左侧c/2头牛的最小aid和,可用一个大小固定为n/2的大根堆来求,每次与堆顶元素比较。
同理可以对称的定义sum2[i]。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=100000+5;
const int INF=0x3f3f3f3f;
int n,c,f,sum1[maxn],sum2[maxn];//sum1[i]表示i左侧c/2头牛的最小aid和 用一个大小固定为n/2的大根堆来求 每次与堆顶元素比较
struct node{
int s,aid;
bool operator<(const node& h)const{return sq;
void pre1(){
while(q.size()) q.pop();
int sum=0,nowf; //堆中所有元素和
for(int i=1;i<=c;i++){
sum1[i]=sum;
if(q.size()) nowf=q.top();
if(q.size()=1;i--){
sum2[i]=sum;
if(q.size()) nowf=q.top();
if(q.size()=n/2+1;i--){ //从大到小依次枚举当前值能否作为中位数
if(cow[i].aid+sum1[i]+sum2[i]<=f){
flag=true;
cout<
POJ 3662: Telephone Lines
二分答案,设当前答案为mid。
将所有边的边权-mid后,权值<=0的边边权设为0,否则为1。
然后,从1到n跑最短路,如果最短路<=k,则满足条件。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
二分答案,设当前答案为mid。
将所有边的边权-mid后,权值<=0的边边权设为0,否则为1。
然后,从1到n跑最短路,如果最短路<=k,则满足条件。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=1000+5;
const int maxp=10000+5;
const int INF=0x3f3f3f3f;
int n,p,k,head[maxn],tot=1,vis[maxn];
dequeq;
struct node{
int from,to,c;
}edge[maxp<<1],edge1[maxp<<1];
void add(int from,int to,int c){
edge[++tot].from=head[from],edge[tot].to=to,edge[tot].c=c;
edge1[tot].from=head[from],edge1[tot].to=to;
head[from]=tot;
}
void init(){
while(q.size()) q.pop_front();
q.push_back(make_pair(1,0));
memset(vis,0,sizeof(vis));
}
int bfs(){
init();
while(q.size()){
pii now=q.front();q.pop_front();
int x=now.first,d=now.second;
if(x==n) return d;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=edge1[i].from){
int y=edge1[i].to,c=edge1[i].c;
if(c==0) q.push_front(make_pair(y,d));
else q.push_back(make_pair(y,d+1));
}
}
return INF;
}
bool check(int mid){
for(int i=2;i<=2*p+1;i++){
edge1[i].c=edge[i].c-mid;
if(edge1[i].c<=0) edge1[i].c=0;
else edge1[i].c=1;
}
return bfs()<=k;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Telephone Lines.in","r",stdin);
cin>>n>>p>>k;
int from,to,c;
for(int i=1;i<=p;i++) cin>>from>>to>>c,add(from,to,c),add(to,from,c);
// D(tot);
int l=0,r=INF;
while(l>1;
if(check(mid)) r=mid;
else l=mid+1;
}
r==INF?cout<<-1:cout<
其他二分搜索
POJ 1759: Garland
因此可以根据和递推。
又因为递推式关于单调递增,所以越小,答案就越小,所以二分即可。
注意天坑:n=3时,答案是-0.00,要纠正为0.00。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
h_i=2*h_i-1-h_i-2+2
因此可以根据h1和h2递推。
又因为递推式关于hi-1单调递增,所以h_2越小,答案就越小,所以二分h2即可。
注意天坑:n=3时,答案是-0.00,要纠正为0.00。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=1000+5;
const int INF=0x3f3f3f3f;
const double eps=1e-5;
int n;
double A;
double cal(double mid){ //计算B
double pre1=A,pre2=mid,temp;
for(int i=3;i<=n;i++){
temp=2*pre2-pre1+2;
pre1=pre2;pre2=temp;
}
return temp;
}
bool check(double mid){
double pre1=A,pre2=mid,temp;
for(int i=3;i<=n;i++){
temp=2*pre2-pre1+2;
if(temp<0) return false;
pre1=pre2;pre2=temp;
}
return true;
}
int main() {
// ios::sync_with_stdio(false);
//freopen("Garland.in","r",stdin);
cin>>n>>A;
double l=0.0,r=(double)INF;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
double ans=cal(l);
if(ans
POJ 3484: Showstopper
原理同防线。
由于只有一个点有奇数个数,则如果某个点的前缀和为奇数,
这个位置一定在左边,否则在右边,二分位置即可。
注意输入很恶心。
代码如下
/*
*/
#define method_1
#ifdef method_1
/*
原理同防线。
由于只有一个点有奇数个数,则如果某个点的前缀和为奇数,
这个位置一定在左边,否则在右边,二分位置即可。
注意输入很恶心。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=20000+5; //poj上有人手测出的二分范围
const int maxp=100+5;
const ll INF=0x3f3f3f3f3f3f3f3fll;
char a[maxn];
int n;
vectorx,y,z;
bool read(){
bool flag=false;
x.clear();y.clear();z.clear();
while(gets(a)){
if(strlen(a)==0){
if(flag==true) break;
else continue;
}
ll xx,yy,zz;
sscanf(a,"%lld%lld%lld",&xx,&yy,&zz);
flag=true;
x.push_back(xx);y.push_back(yy);z.push_back(zz);
}
n=x.size();
return flag;
}
ll check(ll mid){ //求1~mid的前缀和
ll ans=0;
for(int i=0;imid) continue;
ans+=(min(y[i],mid)-x[i])/z[i]+1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
//freopen("Showstopper.in","r",stdin);
while(read()){
ll l=0,r=INF;
while(l>1;
if(check(mid)&1) r=mid;
else l=mid+1;
}
if(r==INF) cout<<"no corruption"<=x[i]){
if((r-x[i])%z[i]==0) tot++;
}
}
cout<