• CF335F Buy One, Get One Free


    题目大意

    你到一家正在进行特价活动的馅饼店买馅饼。规则是每全价购买一个馅饼,都可以免费得到一个价格严格更低的馅饼。
    求出为所有馅饼支付的最小花费。
    (Nle 5e5,A_ile 1e9)

    做法

    自己能想到的最优做法就是(O(n^2))
    考虑dp 一定从大到小 每次选择一段 如果左半部分可以覆盖右半部分就更新 没有单调性也没有优化空间
    题解的做法是可反悔贪心 转化问题为免费拿到的和尽可能大
    也是从大到小排序 接着考虑怎么维护这个反悔过程 考虑维护免费拿过的集合的决策贡献
    一样的一起处理 比如有(cnt)(a) 前面有(s)个馅饼 (c)个免费拿的 还剩(s-2*c)个和当前配对的
    讨论(s-2*cge cnt)于是直接配对扔进集合即可
    否则有剩下的(res)个 考虑对于这几个的决策
    看我们之前拿过的集合里最小的元素(b)(此时(b)有可能小于(a)因为往下看我们有对于决策的修改)
    (b<a) 那一定是把(a)换过去 同时释放了(b)又多了一个位置可以再匹配一个(当然如果只剩一个(a)的话就没有办法扔进去了)
    否则 我们考虑有以下若干种决策
    1.把(b)取出来 放一个(a)进去 释放了(b)再匹配一个(a)(与上面那种决策相同)
    2.保留(b)(a)
    抽象这个过程变为保留(b)再加入一个(2a-b)(当然需要保证至少还存在两个(a) 不过还需要保证(2a-b>0)因为这种决策绝对不优)
    这个抽象过程的正确性在于我们考虑以下过程
    1.最后单选了(2a-b)就是全价买了(b) 把两个名额留给了(a)
    2.最后单选了(b)相当于全价买了两个(a) 提供了两个名额
    3.同时选择了两个(2a-b)(b)也就是相当于既保留了(b)同时又用了两个名额给(a)
    总之就是很高级...

    代码如下:(注释掉的部分是n2)

    //Love and Freedom.
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define inf 20021225
    #define N 500010
    using namespace std;
    int read()
    {
        int s=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')    f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')    s=s*10+ch-'0',ch=getchar();
        return s*f;
    }
    int n,a[N]; ll v[N]; int tot; priority_queue<ll,vector<ll>,greater<ll> > q;
    int main()
    {
    	n=read(); ll ans=0;
    	for(int i=1;i<=n;i++)	ans+=(a[i]=read()); sort(a+1,a+n+1); reverse(a+1,a+n+1);
    	for(int i=1,j;i<=n;i=j)
    	{
    		for(j=i;j<=n&&a[i]==a[j];j++); int cnt=j-i;
    		int cur=min(cnt,i-1-(int)q.size()*2),rst=min(i-1,cnt)-cur; tot=0;
    		for(int x=1;x<=cur;x++)	v[++tot]=a[i];
    		for(int x=1;x<=rst;x+=2)
    		{
    			ll val=q.top(); q.pop();
    			if(val<a[i])
    			{
    				v[++tot]=a[i];
    				if(x<rst)	v[++tot]=a[i];
    			}
    			else
    			{
    				v[++tot]=val;
    				if(x<rst)	v[++tot]=2*a[i]-val;
    			}
    		}
    		for(int x=1;x<=tot;x++)	if(v[x]>=0)	q.push(v[x]);
    	}
    	while(!q.empty())	ans-=q.top(),q.pop();
    	printf("%lld
    ",ans);
    	return 0;
    }
    /**
    ll f[N],a[N],pre[N]; int n,l[N],r[N];
    bool check(int x,int y,int t){int L=max(x,l[y]),R=min(t,r[y]); L-=x,R-=y; return L>R;}
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)	a[i]=read(); sort(a+1,a+n+1); reverse(a+1,a+n+1);
    	for(int i=1;i<=n;i++)	pre[i]=pre[i-1]+a[i],l[i]=a[i]==a[i-1]?l[i-1]:i;
    	for(int i=n;i;i--)	r[i]=a[i]==a[i+1]?r[i+1]:i;
    	for(int i=1;i<=n;i++)
    	{
    		f[i]=f[i-1]+a[i]; int p=i-1;
    		for(int j=i-2;~j;j--)
    		{
    			int mid=i+j+1>>1;
    			if(check(j+1,mid+1,i))	if(f[j]+pre[mid]-pre[j]<f[i])	f[i]=f[j]+pre[mid]-pre[j],p=j;
    		}
    		printf("%d ",p);
    	}
    	printf("%lld
    ",f[n]);
        return 0;
    }*/
    
  • 相关阅读:
    BT协议分析(1)—1.0协议
    Qt线程(2) QThread中使用WorkObject
    新浪微博的开放平台官方文档太粗略,记:仿大平台来实现
    58同城 骗子太多
    代码实现业务经验(程序员的核心能力)
    gitbash 本地文件提交为一个新的项目 到 gitlab
    Spring 核心容器 IOC
    spring AOP 理解
    java不返回某些字段,包括 null
    CentOS7安装 Redis5 单实例
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/14678256.html
Copyright © 2020-2023  润新知