zoukankan      html  css  js  c++  java
  • Codeforces 506C. Mr. Kitayuta vs. Bamboos 题解

    题目链接:C. Mr. Kitayuta vs. Bamboos
    题目大意:你的庄园里用(n)棵竹子,每棵竹子有一个初始高度(h_i),每天会往上张(a_i),你非常不喜欢这些竹子长得很高,所以你要使用魔法将这些竹子给削下来,你会在竹园中待(m)天,每天你会施展(k)次魔法,每一次魔法可以让一棵竹子的高度变为(max(0,h-p))(h)为当前这棵竹子的高度),你想知道在(m)天后竹园中竹子最高高度最小是多少。


    题解:一看到最高高度最小,直接想到二分答案,那么关键就是 check 函数怎么写了,很容易可以想到一个很假的贪心思路,就是把每棵竹子用最小的次数给削下来,但是这里就出问题了,因为你不能把竹子给打到地底下,这就会导致你在打每一棵竹子时会有一个时间限制,这样一个限制下来,似乎就没法做了(当然,官方题解也提供了一种这样走下去的思路,可是我没看懂,果然还是太菜了嘤嘤嘤)。

    “正难则反”,所以考虑对问题进行转化。令二分的答案为(x),我们把每一棵竹子最终的高度都定为(x)(因为它不可能超过(x)),那么从第(m)天开始到第一天为止,竹子每天就不是往天上长,而是往地下钻,而每一次魔法操作则是把竹子给拉上来,可以这样理解,假设我们已经知道了所有的操作并且把它们做成了视频,然后倒着播放,那么限制条件就变为了:

    • 每一棵竹子在每个时刻的高度都不能小于(0)(因为竹子最低高度就是(0)
    • (i)棵竹子在操作完之后的高度不能小于(h_i)(如果大于的话可以从最终高度上减,容易发现这是没有问题的)

    然后这就方便了,可以直接用堆维护将要掉到(0)以下的最小天数,然后贪心地做就可以了。

    时间复杂度:(O((n+mk) ext{log}n ext{log}(h_{max}+a_{max}m))),可以粗略的认为是(O(n ext{log}^2 n))

    代码:

    #include <queue>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    void read(int &a){
    	a=0;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		a=(a<<1)+(a<<3)+(c^48);
    		c=getchar();
    	}
    }
    const int Maxn=100000;
    typedef long long ll;
    int n,m,k,p;
    struct Bamboo{
    	int h,a;
    }a[Maxn+5];
    struct Node{
    	ll day;
    	int id;
    	friend bool operator <(Node p,Node q){
    		if(p.day==q.day){
    			return p.id<q.id;
    		}
    		return p.day<q.day;
    	}
    	friend bool operator >(Node p,Node q){
    		if(p.day==q.day){
    			return p.id>q.id;
    		}
    		return p.day>q.day;
    	}
    	Node(ll _day=0,int _id=0){
    		day=_day;
    		id=_id;
    	}
    };
    priority_queue<Node,vector<Node>,greater<Node> > q;
    int tim[Maxn+5];
    bool check(ll x){
    	while(!q.empty()){
    		q.pop();
    	}
    	for(int i=1;i<=n;i++){
    		if(x-1ll*a[i].a*m<a[i].h){
    			q.push(Node(x/a[i].a,i));
    			tim[i]=0;
    		}
    	}
    	for(int i=1;!q.empty()&&i<=m;i++){
    		for(int j=1;!q.empty()&&j<=k;j++){
    			Node u=q.top();
    			q.pop();
    			if(u.day<i){
    				return 0;
    			}
    			tim[u.id]++;
    			if(x+1ll*tim[u.id]*p-1ll*a[u.id].a*m<a[u.id].h){
    				q.push(Node((x+1ll*tim[u.id]*p)/a[u.id].a,u.id));
    			}
    		}
    	}
    	return q.empty();
    }
    int main(){
    	read(n),read(m),read(k),read(p);
    	ll left=0,right=0;
    	for(int i=1;i<=n;i++){
    		read(a[i].h);
    		read(a[i].a);
    		right=max(right,a[i].h+1ll*m*a[i].a);
    	}
    	while(left<right){
    		ll mid=(left+right)>>1;
    		if(check(mid)){
    			right=mid;
    		}
    		else{
    			left=mid+1;
    		}
    	}
    	cout<<left<<endl;
    	return 0;
    }
    
  • 相关阅读:
    Java SE Development Kit Documentation
    java项目中, mybatis的sql XML文件,在写sql语句时,大于号小于号转义
    java 操作POI参考文章
    java 复制文件
    mysql to sql sersver
    java se 6(jdk1.6) API手册下载地址
    IT编程培训,线上线下,孰优孰劣
    linux单机部署zk集群
    6、定义告警媒介
    5、创建触发器
  • 原文地址:https://www.cnblogs.com/withhope/p/12398897.html
Copyright © 2011-2022 走看看