zoukankan      html  css  js  c++  java
  • 「NOI2017」蔬菜 解题报告

    「NOI2017」蔬菜

    首先考虑流

    可以从 (s) 流入表示得到蔬菜,流出到 (t) 表示卖出蔬菜,给每个蔬菜拆点,并给它它每天应得的蔬菜。

    但是我们没办法直接给,注意到如果把变质看成得到并可以留给上一天,我们每天就可以得到变质的蔬菜并获得从后一天没用完的蔬菜,这就是建图的大体思路。

    然后你发现这个东西需要对询问天数动态加点,加点后发现需要退流,可以暴力退 (m) 的流,复杂度是正确的。

    期望得分 (60)

    然后研究一下,发现退流是没有必要的,也就是说第 (i) 天选择的蔬菜一定是 第 (i+1) 天的子集

    然后你可以写的简单一点。


    考虑实际上,费用流的过程是可以模拟的,或者直接从贪心出发。

    最后一天的选择集合是确定的,并且选择集合只会扩大,不会缩小,然后问题其实就变成了模拟。

    你只需要拿一个堆维护当前可选的蔬菜的集合(注意,蔬菜的大小在外面维护即可)

    对于一血,可以拆成新的一个蔬菜,也可以在进堆的时候特判

    然后可以对每个询问暴力模拟,得到复杂度 (O(nmqlog n)) 的做法

    期望得分 (80)


    然后注意到第 (i) 天可以从第 (i+1) 天进行递推

    维护一个第 (i+1) 天的买的集合,如果集合大小大于 (mi) ,就删掉小的删到 (mi)

    复杂度 (O(nmlog n)) ,期望得分 (100)


    Code:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define ll long long
    using std::min;
    using std::max;
    const int SIZE=1<<21;
    char ibuf[SIZE],*iS,*iT;
    //#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    #define gc() getchar()
    template <class T>
    void read(T &x)
    {
    	int f=0;x=0;char c=gc();
    	while(!isdigit(c)) f|=c=='-',c=gc();
    	while(isdigit(c)) x=x*10+c-'0',c=gc();
    	if(f) x=-x;
    }
    const int N=2e5+10;
    int n,m,k,a[N],s[N],c[N],x[N];
    std::vector<int> seg[N];
    struct node
    {
    	int id,c;
    	node(){}
    	node(int a,int b){id=a,c=b;}
    	bool friend operator <(node a,node b){return a.c<b.c;}
    };
    std::priority_queue <node> q;
    int sta[N],tot,yuu[N*10],sell[N],vis[N],mxt;
    ll ans[N];
    int main()
    {
        //freopen("vegetables2.in","r",stdin);
        //freopen("vegetables2.out","w",stdout);
    	read(n),read(m),read(k);
    	for(int i=1;i<=n;i++)
    	{
    		read(a[i]),read(s[i]),read(c[i]),read(x[i]);
    		//单位收益,一血收益,总库存,每天变质
    		if(x[i]) mxt=max(mxt,(c[i]-1)/x[i]+1);
    	}
    	mxt=min(mxt,100000);
    	if(!mxt) mxt=100000;
    	mxt+=5000;
    	for(int i=1;i<=n;i++)
    	{
    	    if(x[i]) seg[min(mxt,(c[i]-1)/x[i]+1)].push_back(i);
    		else seg[mxt].push_back(i);
    	}
    	for(int sel,i=mxt;i;i--)
    	{
    		for(int j=0;j<seg[i].size();j++)
    		{
    			int id=seg[i][j];
    			q.push(node(id,a[id]+s[id]));
    		}
    		int lim=m;
    		while(lim&&!q.empty())
    		{
    			int now=q.top().id;
    			q.pop();
    			if(!vis[now])
    			{
    				--lim;
    				ans[mxt]+=a[now]+s[now];
    				++sell[now];
    				if(sell[now]!=c[now]) q.push(node(now,a[now]));
    				yuu[++yuu[0]]=a[now]+s[now];
    				vis[now]=1;
    			}
    			else
    			{
    				sel=min(lim,c[now]-x[now]*(i-1)-sell[now]);
    				sell[now]+=sel;
    				lim-=sel;
    				if(sell[now]!=c[now]) sta[++tot]=now;
    				ans[mxt]+=1ll*a[now]*sel;
    				for(int j=1;j<=sel;j++) yuu[++yuu[0]]=a[now];
    			}
    		}
    		for(int j=1;j<=tot;j++) q.push(node(sta[j],a[sta[j]]));
    		tot=0;
    	}
    	std::sort(yuu+1,yuu+1+yuu[0]);
    	for(int j=1,i=mxt;i;i--)
    	{
    		ans[i-1]=ans[i];
    		while(yuu[0]-j+1>(i-1)*m) ans[i-1]=ans[i-1]-yuu[j++];
    	}
    	for(int p,i=1;i<=k;i++) read(p),printf("%lld
    ",ans[min(p,mxt)]);
    	return 0;
    }
    

    2019.6.24

  • 相关阅读:
    set RowCount 与 top n
    Ubuntu 12.04 64bit 安装编译GCC 4.1.2 绝对原创
    C语言第11课
    Cocos2d-x之MenuItem
    wamp 已安装cakephp Fatal error: You must enable the intl extension to use CakePHP. in XXX
    jQuery性能优化38建议---最引人注目的用户体验!
    在面对变化,撇开NO
    批学习
    JAVA修饰符类型(public,protected,private,friendly)
    【Espruino】NO.15 nRF24L01+无线收发器
  • 原文地址:https://www.cnblogs.com/butterflydew/p/11075908.html
Copyright © 2011-2022 走看看