NOI2017 day2T2 vegetables 题解(伪)

阅读: 评论:0

NOI2017 day2T2 vegetables 题解(伪)

NOI2017 day2T2 vegetables 题解(伪)

(同步赛的时候day2的T2T3都爆0了...我这么弱还是回家搞文化吧)

这题首先注意题意.我们发现题意实际上是说,有很多份能买一次的蔬菜,它们有一个价值和一个变质时间.第一次卖的每种蔬菜可以认为是最后变质的(我们肯定希望更有价值的更好卖)

接下来把所有蔬菜按价值从大到小放在一个优先队列里(或者说直接排序也可以),对于每份蔬菜,如果能刚好在它变质那一天卖掉,就在它变质那一天卖掉;否则看变质前一天...以此类推.正确性的话...放弃一份价值高的蔬菜最多能多卖出一份价值低的蔬菜,肯定是不划算的.更晚卖肯定比更早卖优.

用上面的方法加上一些优化大概有80分.

考虑先算出p最大的那一天的收益.把每种蔬菜放进优先队列里(第一次卖的单独再算一种),接下来从这种蔬菜最后变质的一份变质的那一天开始,如果那一天能卖完就卖完,否则就会有剩余到前一天,以此一直推到第0天.注意两个保证复杂度的细节:用并查集快速处理连续的不能再卖东西的几天;如果一种蔬菜不会变质,而且已经没有剩余,则要及早跳出循环.

上面这个过程的复杂度大约是(2nlogn+m*max(p)*(并查集复杂度)),大约是1e6或者1e7级别的.

接下来计算之前每一天的收益.把所有可以被卖掉的蔬菜放进一个优先队列里.每当减少一天时,就把价值最小的m份蔬菜的价值减掉.这样就处理出了每一天的收益.复杂度(m*max(p)*log(m*max(p))),大约是1e7级别.(这个过程可以看做是把最后一天的蔬菜替换掉了之前价值最小的蔬菜的蔬菜)

至此,这个问题就被解决了.这只是我的方法,如果有错误欢迎指出QAQ.

(赛场上看错题了真是***)

具体细节见代码.(顺便,%%%dy)

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<queue>
using namespace std;
const int maxm=100000;//maxm是最大天数
int Min(int x,int y){return x<y?x:y;
}
int Max(int x,int y){return x>y?x:y;
}
struct Node{int a,s,c,x;void readl(){scanf("%d%d%d%d",&a,&s,&c,&x);}
}b[100100];
struct node{int a,c,x;
}d[200100];
bool cmp(const node &A,const node &B){return A.a>B.a;
}
int g[1001000];
int num,cnt;
int m;
int f[100100];
int dis[100100];
long long dp[100100];
int getfa(int x){//用一种鬼畜方式写的并查集if(dis[f[x]]<m) return f[x];return f[x]=getfa(f[x]-1);
}
int main()
{freopen("vegetables.in","r",stdin);freopen("vegetables.out","w",stdout);int n,T,cas;scanf("%d%d%d",&n,&m,&T);for(int i=1;i<=n;i++)b[i].readl();for(int i=1;i<=n;i++){if(b[i].c>1)d[++num]=(node){b[i].a,b[i].c-1,b[i].x};if(b[i].x==0)d[++num]=(node){b[i].a+b[i].s,maxm,-1};//把第一次卖的单独考虑,注意特殊处理x=0的情况elsed[++num]=(node){b[i].a+b[i].s,(b[i].c-1)/b[i].x+1,-1};}sort(d+1,d+num+1,cmp);for(int i=1;i<=100000;i++)f[i]=i;node st;int ps,s,t,lef;long long ans=0;for(int i=1;i<=num;i++){st=d[i];if(st.x==-1){t=getfa(Min(st.c,maxm));if(t<=0) continue;dis[t]++,g[++cnt]=st.a;ans=ans+st.a;}else{t=(st.x==0?maxm:Min(maxm,(st.c-1)/st.x+1));	//最后变质的一天,同样注意x==0的情况lef=st.c-st.x*(t-1);//当前剩余可以卖的蔬菜数量while(t>0){while(lef>0&&dis[t]<m){lef--;dis[t]++,g[++cnt]=st.a;ans=ans+st.a;}if(lef==0&&st.x==0) break;//如果不加这句话,就会导致进入大循环次数过多s=getfa(t-1);lef+=(t-s)*st.x;t=s;}}}dp[maxm]=ans;cnt=maxm*m;sort(g+1,g+cnt+1);//g是所有卖出去了的蔬菜int ilem=1;for(int i=maxm-1;i>=1;i--){for(int j=1;j<=m;j++){ans-=g[ilem];ilem++;}dp[i]=ans;//dp是答案}for(cas=1;cas<=T;cas++){scanf("%d",&ps);printf("%lldn",dp[ps]);}return 0;
}


本文发布于:2024-01-30 13:40:12,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170659321520386.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:题解   vegetables
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23