zoukankan      html  css  js  c++  java
  • [NOI2017]蔬菜(贪心)

    神仙题啊!

    早上开了两个多小时,终于肝出来了,真香

    我们考虑从第 (10^5) 天开始递推,先生成 (p=10^5) 的解,然后逐步推出 (p-1,...,2,1) 的解。

    那怎么推出 (p=10^5) 的解呢?

    现在将题目转化成不停进货然后取 (m) 个最大的问题,然后删除最大并 (push) 进去。这我们可以想到大根堆。

    但是由于政策 增加题目难度,有一个 (s)。我们需要先将 ((a_i+s_i,i)) (push) 进去,然后用掉了以后将 ((a_i,i)) (push) 进去。

    因为在第 (i) 天买了一种蔬菜,当天就无需再用,我们考虑用一个栈存储一下当天用了不是 (a+s) 的蔬菜,

    然后 (p=10^5) 的解生成完了以后,现在就是生成其他解了。

    我们每次将最小的 (sum-i*m) 个取出然后删除。此时我们也要特判政策。

    答案要开 (long long),时间复杂度 (O(pmlog n))

    (Code Below:)

    #include <bits/stdc++.h>
    #define ll long long
    #define pii pair<int,int>
    #define mp make_pair
    #define F first
    #define S second
    using namespace std;
    const int maxn=100000+10;
    const int lim=100000;
    int n,m,k,a[maxn],s[maxn],c[maxn],x[maxn],used[maxn],sum,top;
    vector<int> v[maxn];ll ans[maxn];pii sta[maxn];
    priority_queue<pii> pq;
    
    inline int read(){
    	register int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return (f==1)?x:-x;
    }
    
    int main()
    {
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=n;i++){
    		a[i]=read(),s[i]=read(),c[i]=read(),x[i]=read();
    		if(x[i]==0) v[lim].push_back(i);
    		else v[(c[i]+x[i]-1)/x[i]].push_back(i);
    	}
    	pii u;int rest;
    	for(int i=lim;i>=1;i--){
    		for(int j=0;j<v[i].size();j++) pq.push(mp(a[v[i][j]]+s[v[i][j]],v[i][j]));
    		for(int j=m;j>=1&&!pq.empty();){
    			u=pq.top(),pq.pop();
    			if(!used[u.S]){
    				used[u.S]++;ans[lim]+=u.F;j--;
    				if(used[u.S]!=c[u.S]) pq.push(mp(a[u.S],u.S));
    			}
    			else {
    				rest=min(j,c[u.S]-used[u.S]-(i-1)*x[u.S]);
    				ans[lim]+=(ll)rest*a[u.S];used[u.S]+=rest;j-=rest;
    				if(used[u.S]!=c[u.S]) sta[++top]=mp(a[u.S],u.S);
    			}
    		}
    		while(top) pq.push(sta[top--]);
    	}
    	while(!pq.empty()) pq.pop();
    	for(int i=1;i<=n;i++) sum+=used[i];
    	for(int i=1;i<=n;i++){
    		if(used[i]==1) pq.push(mp(-a[i]-s[i],i));
    		else if(used[i]) pq.push(mp(-a[i],i));
    	}
    	for(int i=lim-1;i>=1;i--){
    		ans[i]=ans[i+1];
    		while(sum>i*m&&!pq.empty()){
    			u=pq.top(),pq.pop();u.F=-u.F;
    			if(used[u.S]==1) ans[i]-=u.F,sum--,used[u.S]=0;
    			else {
    				rest=min(sum-i*m,used[u.S]-1);
    				sum-=rest;used[u.S]-=rest;ans[i]-=(ll)rest*a[u.S];
    				if(used[u.S]==1) pq.push(mp(-a[u.S]-s[u.S],u.S));
    				else pq.push(mp(-a[u.S],u.S));
    			}
    		}
    	}
    	while(k--) printf("%lld
    ",ans[read()]);
    	return 0;
    }
    
  • 相关阅读:
    Codeforces 1316B String Modification
    Codeforces 1305C Kuroni and Impossible Calculation
    Codeforces 1305B Kuroni and Simple Strings
    Codeforces 1321D Navigation System
    Codeforces 1321C Remove Adjacent
    Codeforces 1321B Journey Planning
    Operating systems Chapter 6
    Operating systems Chapter 5
    Abandoned country HDU
    Computer HDU
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10253806.html
Copyright © 2011-2022 走看看