zoukankan      html  css  js  c++  java
  • [NOI2017]蔬菜——时光倒流+贪心

    题目链接

    题解:

    貌似一眼看过去是一个贪心。

    其他的算法要记录的东西就太多了。


    部分分其实很高。但是没有什么提示。

    想一些套路:二分?不行还要贪心判断。

    分治?前后取法是有影响的。

    时光倒流?

    也许可以?

    其实比较麻烦的是蔬菜变质。这样就使得我们不能每次卖最贵的。

    如果时光倒流,那么就会有些蔬菜在某一个时刻以某一个初值出现,然后每过一天,增长固定的个数。

    那么,面对最后一天,我们就剩下这么多的菜了。肯定要卖最贵的m个

    然后,倒数第二天,一些蔬菜出现了,一些蔬菜变多了,我们在最后一天卖菜的基础上,可以继续选择最贵的m个。

    因为,最后一天的菜和倒数第二天的菜交换一定不优,因为可能倒数第二天能买到的,最后一天就坏了。而由于取最大的m个,某天卖其他的菜也不会更优。

    类似数学归纳法可以证明。

    现在我们可以找出来p天的最大收益了。

    但是,询问太多了, 可以不可以递推呢?

    可以。

    求出max(pi)的值mxans

    然后,每往前提一天,那么,就把所有卖过的菜中,删掉最便宜的m个。

    合法显然,因为后面能卖的,前面一定能卖、

    如果不卖这些,同层之间交换不优的。

    离线处理,然后倒序递推即可。

    细节比较多:

    1.不能除以0

    2.等等

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize"Ofast"
    #include<bits/stdc++.h>
    #define ri register int 
    using namespace std;
    #define int long long
    #define numb (ch^'0')
    typedef long long ll;
    const int N=2e5+5;
    void rd(int &x){
        char ch;x=0;
        while(!isdigit(ch=getchar()));
        for(x=numb;isdigit(ch=getchar());x=(x<<1)+(x<<3)+numb);
    }
    struct node{
        ll val;
        int id;
        int sold;
        bool friend operator <(node a,node b){
            return a.val<b.val;
        }
    }sta[N];
    int top;
    ll mxans;
    int val[N],c[N],s[N],dele[N];
    int sell[N];
    int app[N],rem[N];
    priority_queue<node>q1;
    struct bac{
        ll val;
        ll sum;
        bool friend operator <(bac a,bac b){
            return a.val>b.val;
        }
    };
    priority_queue<bac>q2;
    int n,m,k;
    struct question{
        int day;
        int id;
        bool friend operator<(question a,question b){
            return a.day>b.day;
        }
    }que[N];
    ll ans[N];
    int up;
    int id[N];
    vector<int>mem[N];//appear day
    bool cmp(int a,int b){
        return val[a]>val[b];
    }
    signed main(){
        rd(n);rd(m);rd(k);
        bool fl=true;
        for(ri i=1;i<=n;i++){
            rd(val[i]),rd(s[i]),rd(c[i]),rd(dele[i]);
            if(dele[i]) fl=false;
        }
        for(int i=1;i<=k;i++){
            rd(que[i].day);
            //scanf("%d",&que[i].day);
            que[i].id=i;
        }sort(que+1,que+k+1);
        up=que[1].day;
        //cout<<que[k-1].day<<endl;
        //cout<<" up "<<up<<endl;
        for(ri i=1;i<=n;i++){
            if(dele[i]==0){
                app[i+n]=up;
                rem[i+n]=1;
                dele[i+n]=0;
                c[i+n]=1;
                val[i+n]=s[i]+val[i];
                mem[app[i+n]].push_back(i+n);
                
                c[i]--;
                if(c[i]==0) continue;//warning!!
                int exi=up;
                int re=c[i];
                app[i]=exi,rem[i]=re;
                mem[exi].push_back(i);
                continue;
            }
            app[i+n]=(c[i]+dele[i]-1)/dele[i];
            if(app[i+n]>up) app[i+n]=up;
            rem[i+n]=1;
            dele[i+n]=0;
            c[i+n]=1;
            val[i+n]=s[i]+val[i];
            mem[app[i+n]].push_back(i+n);
            
            c[i]--;
            if(c[i]==0) continue;//warning!!
            int exi=(c[i]+dele[i]-1)/dele[i];
            int re=c[i]%dele[i];
            if(re==0) re=dele[i];
            if(exi>up){
                re+=(exi-up)*dele[i];
                exi=up;
            }
            app[i]=exi,rem[i]=re;
            mem[exi].push_back(i);
        }    
        //for(int i=1;i<=2*n;i++){
        ///    cout<<i<<" : "<<val[i]<<" "<<c[i]<<" "<<app[i]<<" "<<rem[i]<<endl;
        //}
        if(fl){
            for(int i=1;i<=2*n;i++) {
                id[i]=i;
            }
            sort(id+1,id+2*n+1,cmp);
            int ptr=k;
            if(que[ptr].day==0) ptr--;
            int r=1;
            //cout<<" day "<<que[ptr].day<<endl;
            for(int d=1;d<=up;d++){
                int now=id[r];
                //cout<<d<<" : "<<r<<" : "<<c[now]<<endl;
                int nd=m;
                while(r<=2*n&&c[id[r]]<nd){
                    int now=id[r];
                    nd-=c[now];
                    mxans+=val[now]*c[now];
                    r++;
                }
                //cout<<" nd "<<nd<<" "<<r<<endl;
                if(r<=2*n){
                    int now=id[r];
                    c[now]-=nd;
                    mxans+=val[now]*nd;
                }
                while(que[ptr].day==d&&ptr){
                    //cout<<que[ptr].id<<endl;
                    ans[que[ptr].id]=mxans;ptr--;
                }
                //cout<<ptr<<endl;
            }
            //cout<<r<<" "<<mxans<<endl;
            for(int i=1;i<=k;i++){
            printf("%lld
    ",ans[i]);
            }
            return 0;
        }
        for(ri i=up;i>=1;i--){
            for(ri j=0;j<mem[i].size();j++){
                int id=mem[i][j];
                node tmp;tmp.val=(ll)val[id];tmp.id=id;tmp.sold=0;
                q1.push(tmp);
            }
            int nd=m;
            while(nd){
                if(q1.empty()) break;
                node now=q1.top();q1.pop();
                int has=(app[now.id]-i)*dele[now.id]+rem[now.id]-now.sold;
                //cout<<" has "<<now.id<<" : "<<has<<endl;
                if(has>nd){
                    now.sold+=nd;
                    mxans+=val[now.id]*nd;
                    sell[now.id]+=nd;
                    nd=0;
                }
                else{
                    now.sold+=has;
                    mxans+=val[now.id]*has;
                    sell[now.id]+=has;
                    nd-=has;
                }
                if(now.id<=n) sta[++top]=now;//warning!! id>n not push back
            }
            while(top){
                q1.push(sta[top]);top--;
            }
            //cout<<" after "<<i<<" : "<<mxans<<endl;
        }
        ans[que[1].id]=mxans;
        if(k==1){
            printf("%lld",mxans);
            return 0;
        }
        int tot=0;
        for(ri i=1;i<=2*n;i++){
            if(sell[i]){
                tot+=sell[i];
                bac tmp;
                tmp.sum=sell[i];
                tmp.val=(ll)val[i];
                q2.push(tmp);
            }
        }
        int ptr=2;
        for(ri i=up;i>=1;i--){
            while(ptr<=k&&que[ptr].day==i){
                ans[que[ptr].id]=mxans;ptr++;
            }
            if((i-1)*m>=tot) continue;//warning!!!
            if(i==1) break;
            int nd=min(m,tot-((i-1)*m));
            while(nd){
                if(q2.empty()) break;
                bac now=q2.top();q2.pop();
                if(now.sum>nd){
                    now.sum-=nd;
                    mxans-=nd*now.val;
                    nd=0;
                    q2.push(now);
                }
                else{
                    mxans-=now.sum*now.val;
                    nd-=now.sum;
                }
            }
        }
        for(int i=1;i<=k;i++){
            printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/10/14 14:19:49
    */
  • 相关阅读:
    UMLChina-我不经意的创业故事
    oracle management server
    关于做PDF的FAQ(一)~(四)
    关于学习ASP和编程的28个观点
    JavaScript的方法和技巧
    在公告栏里加进啦Google自定义搜索引擎(附代码,和参考代码,原代码)
    来北京工作了,有写感慨
    asp.net 2.0 访问oracle
    利用SharpZipLib进行文件的压缩和解压缩
    软件工程师,请不要做浮躁的人
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9799530.html
Copyright © 2011-2022 走看看