A. Buying Torches
题意:起初有一个木棒 然后有2个操作
- 将一个木棒换成x个木棒
- 将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;
}