(Training 23)Educational Codeforces Round 95

A. Buying Torches

题意:起初有一个木棒 然后有2个操作

  1. 将一个木棒换成x个木棒
  2. 将y个木棒换成1个木炭

一个火把需要一个木棒和一个火把
问k个火把需要进行最少操作
思路:首先一共需要多少木棒 y*k+k
然后得到这么多木棒的最少操作次数 最后就是k次将木棒换成木炭的次数 计算出即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int main(){
	int T;
	cin>>T;
	while(T--){
		long long x,y,k;
		cin>>x>>y>>k;
		long long sum=(k)*y+k-1;//需要木棒数量=木棒数量+木炭*(k-1) 
		//cout<<sum<<endl;
		long long ans=(sum+x-2)/(x-1)+k;//每次交易增加x-1木棒 
		cout<<ans<<endl; 
	} 
	return 0;
} 

B - Negative Prefixes

题意:给出1个长度为n的序列 固定一些位置 然后你可以进行交换没有固定位置的 数 使得前缀和为负的靠前
思路:将所有的没固定的大的数放在前面即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N],st[N];
bool cmp(int x,int y){
	return x>y;
}
int main(){
	int T;
	cin>>T;
	while(T--){
		memset(st,0,sizeof st);
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		int bn=0;
		int sum1=0,sum2=0;
		for(int i=1;i<=n;i++){
			int x;
			scanf("%d",&x);
			st[i]=x;
			if(x==0){
				b[++bn]=a[i];
			}
		}
		sort(b+1,b+1+bn,cmp);
		for(int i=1,j=0;i<=n;i++){
			if(st[i])printf("%d ",a[i]);
			else printf("%d ",b[++j]);
		}
		puts("");
	} 
	return 0;
} 

C. Mortal Kombat Tower

题意:你和朋友进行游戏 朋友先打 凡是boss系数为0他打得过 否则需要跳过
然后交换由你来进行操作 你可以打所有怪物 你们如何打怪使得跳过次数最少
每个人每次操作最多连续打2个怪
思路:考虑每个点都只会从前2个或者前1个转移
就是一个很简单的dp

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int a[N],b[N],f[N][3];
int main(){
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			f[i][0]=f[i][1]=0x3f3f3f3f;
		}
		f[1][0]=a[1]==1;
		f[2][1]=f[1][0]+(a[2]==1);
		f[3][0]=f[1][0]+(a[3]==1);//除了这几个均为不合法状态 
		for(int i=4;i<=n;i++){
			f[i][0]=min({f[i-2][1],f[i-2][0],f[i-3][1],f[i-3][0]})+(a[i]==1);
			f[i][1]=f[i-1][0]+(a[i]==1);
		}
		int res=0x3f3f3f3f;
		for(int i=n;i>=n-2&&i>=1;i--){
			res=min({res,f[i][1],f[i][0]});
		}
		cout<<res<<endl;
	} 
	return 0;
} 

D. Trash Problem

题意:一个x坐标下有n堆垃圾
垃圾只能一个一个位置的一定
问移动到2堆最少移动多少次 然后有q次修改
如果为0 x
那么就是将x上的垃圾去除
如果为1 x
那么就是将x上增加垃圾
问每次修改的时候 最少操作是多少
思路:我们用2个set维护垃圾的位置和 垃圾间的距离
因为set有序 而每次操作我们合并成2堆必然是将垃圾距离最远的2堆分别合到不同的2堆 所以每次的操作数就是左端点和右端点的距离差 然后减去距离最大的 然后每次set维护即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int N=2e5+10,inf=0x3f3f3f3f;
multiset<int>dis,p;
int a[N];
void cal(){
	if(p.size()<=4)puts("0");
	else printf("%d\n",(*----p.end())-(*++p.begin())-(*--dis.end()));
}
void change(int op,int x){
	int pre=*--p.lower_bound(x);
	int suf=*p.upper_bound(x);
	if(op==1){
		p.insert(x);
		if(pre>-inf&&suf<inf)dis.erase(dis.find(suf-pre));
		if(pre>-inf)dis.insert(x-pre);
		if(suf<inf)dis.insert(suf-x);
	} 
	else{
		p.erase(x);
		if(pre>-inf&&suf<inf)dis.insert(suf-pre);
		if(pre>-inf)dis.erase(dis.find(x-pre));
		if(suf<inf)dis.erase(dis.find(suf-x));
	}
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	p.insert(-inf);
	p.insert(inf);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		p.insert(a[i]);
	}
	sort(a+1,a+1+n);	
	for(int i=1;i<n;i++){
		dis.insert(a[i+1]-a[i]);
	}
	cal();
	for(int i=1;i<=m;i++){
		int op,x;
		scanf("%d%d",&op,&x);
		change(op,x);
		cal();
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值