返回顶部

“深圳计算科研院杯“E起来编程暨第三届湖北省赛 B.Mr.Maxwell and attractions (优先队列,前缀和)

  • 题意:你要连续\(T\)天去景点游玩(上午或者下午),有\(n\)个室内景点和\(m\)个室外景点,每个景点都有自己的值,对于同一个景点,每次重复参观,权值都要*\(0.6\).如果在下午参观室外景点那么景点的权值*\(0.8\).你至少有\(k\)天在下午游玩,问你能得到的最大权值是多少.

  • 题解:对于*\(0.6\)这个条件,室内和室外都是一样的,可以用两个优先队列分别来维护,以保证它们的权值都是单调递减的,在维护的同时记两个前缀和,然后我们再\(O(n)\)遍历一遍,选\(i\)天上午去室外(\(i>(t-k)\)的部分要*0.8),\(t-i\)天下午去室内,用前缀和来更新答案.

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n,m,t,k;
    double pre1[N],pre2[N];
    
    double Max(double a,double b){
    	if(a>b) return a;
    	else return b;
    }
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	cin>>n>>m>>t>>k;
    	k=t-k;
    	priority_queue<double> a,b;
    	rep(i,1,n){
    		double x;
    		cin>>x;
    		a.push(x);
    	}
    	rep(i,1,m){
    		double x;
    		cin>>x;
    		b.push(x);
    	}
    	
    	rep(i,1,t){
    		double cur=a.top();
    		a.pop();
    		pre1[i]=pre1[i-1]+cur;
    		cur*=0.6;
    		a.push(cur);
    		cur=b.top();
    		b.pop();
    		pre2[i]=pre2[i-1]+cur;
    		cur*=0.6;
    		b.push(cur);
    	}
    
    	double ans=0.0; 
    	rep(i,1,t){
    		if(i<=k) ans=Max(ans,pre2[i]+pre1[t-i]);
    		else ans=Max(ans,pre2[k]+(pre2[i]-pre2[k])*0.8+pre1[t-i]);
    	}
    
    	cout<<fixed<<setprecision(2)<<ans<<'\n';
    	
        return 0;
    }
    
    
posted @ 2021-05-07 11:52  _Kolibri  阅读(70)  评论(0)    收藏  举报