zoukankan      html  css  js  c++  java
  • 【二分】P1462 通往奥格瑞玛的道路

    前置芝士:二分

    [P1182]

    对于给定的一个长度为N的正整数数列 (A_{1 sim N}),现要将其分成 (M (M≤N))段,并要求每段连续,且每段和的最大值最小。

    眼神告诉我,每段和的最大值满足:

      1.有上下界。
      2.有单调性。
    

    求最值考虑二分。
    每段和的最大值上界即为所有数之和,下界为数列元素的最大值。
    二分到x后check(x),计算若每段之和不大于x可以分多少段,若大于等于m则向上二分,否则向下二分。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    int n,m,a[maxn];
    int l,r,tot,cnt;
    bool judge(int x,int a[]){
    	for(int i=0;i<n;i++){
    		if(tot+a[i]<=x)tot+=a[i];
    		else tot=a[i],cnt++;
    	}
    	return cnt>=m;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;i++){
    		scanf("%d",&a[i]);
    		r+=a[i];
    		l=l>a[i]?l:a[i];
    	}
    	while(l<=r){
    		int mid=l+r>>1;
    		tot=cnt=0;
    		if(judge(mid,a))l=mid+1;
    		else r=mid-1;
    	}
    	printf("%d",l);
    	return 0;
    }
    



    P1462 (dij+二分)

    同理,交费的最大值上界为F数组的最大值,下界不确定(没有限制,就用1吧)。
    然后以二分到的x为最大值check,判断是否有一条路可以使得每条边的收费都小于等于此值并且走到终点之后血量不会被扣光。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=10010;
    #define ll long long
    ll f[maxn],dis[maxn],b,v;
    vector<pair<int,ll> >vec[maxn];
    priority_queue<pair<ll,int> >q;
    int vis[maxn],n,m,x,y;
    
    int check(int x){
    	if(f[1]>x)return 0;
    	for(int i=1;i<=n;i++)dis[i]=1e18,vis[i]=0;
    	dis[1]=0;
    	q.push(make_pair(0,1));
    	while(!q.empty()){
    		int u=q.top().second;
    		q.pop();
    		if(vis[u])continue;
    		vis[u]=1;
    		for(int i=0;i<vec[u].size();i++){
    			int v=vec[u][i].first;
    			if(f[v]>x)continue;
    			ll w=vec[u][i].second;
    			if(dis[u]+w<dis[v]){
    				dis[v]=dis[u]+v;
    				q.push(make_pair(-dis[v],v));
    				if(v==n){
    					if(dis[n]>=b)return 0;
    					else return 1;
    				}
    			}
    		}
    	}
    	return 0;
    }
    
    int main(){
    	ll mxx=-1;
    	scanf("%d%d%lld",&n,&m,&b);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&f[i]);
    		mxx=max(mxx,f[i]);
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%lld",&x,&y,&v);
    		vec[x].push_back(make_pair(y,v));
    		vec[y].push_back(make_pair(x,v));
    	}
    	ll ans=-1,l=1,r=mxx;
    	while(l<=r){
    		ll mid=l+r>>1;
    		if(check(mid))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	if(ans==-1)puts("AFK");
    	else printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    SQL常规查询详解
    WEBGL学习【二】平面图形
    WEBGL学习【一】初识WEBGL
    VS2008集成QT的OpenGL开发(实现二维图形的旋转)
    Window文件路径
    字符串转DateTime
    字符串连接
    String.Split分隔字符串
    使用对象初始值设定项初始化
    表达式树
  • 原文地址:https://www.cnblogs.com/zdxx/p/13787669.html
Copyright © 2011-2022 走看看