Codeforces Round #398 (Div. 2)解题报告

Problem A- Snacktower

模拟,贪心,每次找最大的

//Author: Lixiang
#include<stdio.h>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100001;
struct Snacktower{
	int a[maxn],b[maxn],N;
	void init(){
		scanf("%d",&N);
		for(int i=1;i<=N;i++)
			scanf("%d",&a[i]),b[i]=a[i];
	}
	void work(){
		sort(a+1,a+N+1);
		set<int> s;
		int now=N;
		for(int i=1;i<=N;i++){
			s.insert(b[i]);
			while(s.find(a[now])!=s.end())
				printf("%d ",a[now--]);
			puts("");
		}
	}
}sol;
int main(){
	sol.init();
	sol.work();
	return 0;
}



Problem B- The Queue

模拟每个顾客的结束时间
注意特判:接待员在t2的时间点如果没处理完,就停止处理了。

//Author: Lixiang
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=100001;
struct Queue{
	long long ts,tf,t,a[maxn],b[maxn],c[maxn];
	int N;
	void init(){
		scanf("%I64d%I64d%I64d",&ts,&tf,&t);
		scanf("%d",&N);
		for(int i=1;i<=N;i++)
			scanf("%I64d",&a[i]);
	}
	void work(){
		int cnt=0;
		if(a[1]>ts){
			printf("%I64d\n",ts);
			return;
		}
		for(int i=1;i<=N;i++){
			int num=1;
			if(a[i]>=tf)break;
			while(i<N&&a[i+1]==a[i]){
				num++;
				i++;
			}
			b[++cnt]=a[i];
			c[cnt]=num;
		}
		
		long long ans=ts-a[1]+1,sol=a[1]-1;
		if(a[1]==0)ans=tf;
		b[0]=ts;c[0]=0;
		for(int i=1;i<cnt;i++){
			b[i]=max(b[i-1]+t*c[i-1],b[i]);
			if(b[i]+t*(c[i]+1)>tf)break;
			if(b[i]+t*c[i]-b[i+1]+1<ans){
				ans=b[i]+t*c[i]-b[i+1]+1;
				sol=b[i+1]-1;
			}
		}
		b[cnt]=max(b[cnt-1]+t*c[cnt-1],b[cnt]);
		if(b[cnt]+t*(c[cnt]+1)<=tf)sol=b[cnt]+t*c[cnt];
		printf("%I64d\n",sol);
	}
}sol;
int main(){
	sol.init();
	sol.work();
	return 0;
}

Problem C- Garland

DFS,找子树和为sum/3。

注意优化:注意找到两个就可以输出了。

//Author: Lixiang
#include<stdio.h>
#include<vector>
#include<stdlib.h>
using namespace std;
const int maxn=1000001;
struct Garland{
	vector <int> ADJL[maxn];
	int w[maxn],s[maxn],ans[5],N,root,cnt,tot;
	bool hash[maxn];
	void init(){
		scanf("%d",&N);
		for(int i=1,v;i<=N;i++){
			scanf("%d%d",&v,&w[i]);
			if(v==0)root=i;
			else ADJL[v].push_back(i);
			tot+=w[i];
		}
	}
	int getsum(int now){
		if(cnt==2){
			printf("%d %d\n",ans[1],ans[2]);
			exit(0);
		}
		vector <int>::iterator it;
		s[now]=w[now];
		for(it=ADJL[now].begin();it!=ADJL[now].end();it++)
			s[now]+=getsum(*it);
		if(s[now]==tot){
			ans[++cnt]=now;
			s[now]=0;
		}
		return s[now];
	}
	void work(){
		if(tot%3!=0){
			puts("-1");
			return ;
		}
		tot/=3;
		getsum(root);
		if(cnt>=3)printf("%d %d\n",ans[1],ans[2]);
		else puts("-1");
	}
}sol;
int main(){
	sol.init();
	sol.work();
	return 0;
}

Problem D-Cartons of milk

简单贪心

从最后一天往前推,让已有的Carton尽量在保质期那天喝掉,然后对于每一天添加新的Carton

//Author: Lixiang
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1000001;
const int maxf=10000001;
struct Milk{
	int date,id;
	void in(int i){
		scanf("%d",&date);
		id=i;
	}
	bool operator<(Milk b){
		return date<b.date;
	}
};
struct Cartons_of_milk{
	queue <int> Q;
	Milk B[maxn];
	int A[maxf],N,M,K,Mi,Ma;
	void init(){
		scanf("%d%d%d",&N,&M,&K);
		Mi=10000000,Ma=0;
		for(int i=1,tmp;i<=N;i++){
			scanf("%d",&tmp);
			A[tmp]++;
			Ma=max(tmp,Ma);
			Mi=min(tmp,Mi);
		}
		for(int i=1;i<=M;i++)
			B[i].in(i);
		sort(B+1,B+M+1);
	}
	void work(){
		for(int i=Ma;i>Mi;i--)
			if(A[i]>K){
				A[i-1]+=A[i]-K;
				A[i]=K;
			}
		if(A[Mi]>K){
			if(Mi==0){
				puts("-1");
				return ;
			}
			A[Mi-1]+=A[Mi]-K;
			A[Mi]=K;
		}
		int id=1;
		for(int i=0;i<=B[M].date&&id<=M;i++)
			if(A[i]<K){
				while(id<=M&&B[id].date<i)id++;
				for(int j=1;j<=K-A[i]&&id<=M;j++)
					Q.push(B[id++].id);
			}
		printf("%d\n",Q.size());
		while(!Q.empty()){
			printf("%d ",Q.front());
			Q.pop();
		}
	}
}sol;
int main(){
	sol.init();
	sol.work();
	return 0;
}


Problem E- Change Free

贪心,模拟每天购买过程,对于每一次必须要用纸币的天,找前面的天中不满值最小的那天换。

//Author: Lixiang
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn=100001;
struct Node{
	long long val;
	int id;
	Node make(long long v,int i){
		val=v;id=i;
		return *this;
	}
	bool operator <(Node b)const{
		return val>b.val;
	}
}tmp;
struct Change_Free{
	priority_queue <Node> H;
	long long c[maxn],w[maxn],below[maxn],over[maxn];
	int N,M;
	bool change[maxn];
	void init(){
		scanf("%d%d",&N,&M);
		for(int i=1;i<=N;i++)scanf("%I64d",&c[i]);
		for(int i=1;i<=N;i++){
			scanf("%I64d",&w[i]);
			below[i]=c[i]%100;
			over[i]=100-below[i];
		}
	}
	void work(){
		long long ans=0,now=M;
		for(int i=1;i<=N;i++){
			if(below[i]==0)continue;
			H.push(tmp.make(over[i]*w[i],i));
			if(below[i]>now){
				change[H.top().id]=1;
				ans+=H.top().val;
				now=now+100;
				H.pop();
			}
			now-=below[i];
		}
		printf("%I64d\n",ans);
		for(int i=1;i<=N;i++){
			if(change[i]){
				if(c[i]%100!=0)printf("%I64d 0\n",c[i]/100+1);
				else printf("%I64d 0\n",c[i]/100);
			}
			else printf("%I64d %I64d\n",c[i]/100,c[i]%100);
		}
	}
}sol;
int main(){
	sol.init();
	sol.work();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值