Acwing蓝桥杯集训·题解week3
炮弹
按照题意模拟:
注意两点:
1.死循环,如果存在两个能量为0跳板,就会互相弹跳,停不下来,设置一个合理的循环上限,防止超时
2.时间复杂度:在最坏的情况下
k最开始为1,跳n次,k为2时,跳2/n次.....
所以在最坏的情况下时间复杂度\(O(\sum_{i=1}^{n}\frac{n}{i})=O(nlnn)\)是调和级数的时间复杂度
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,s;
const int maxn=1e5+10;
struct node{
int q,v;
}e[maxn];
int nex=1;
int ans=0;
bool flag[maxn];
int check[maxn][3];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>s;
for(int i=1;i<=n;++i) cin>>e[i].q>>e[i].v;
bool book=1;
int cnt=0;
while(s>=1 && s<=n && cnt<=n*26){
// cout<<s<<endl;
if(e[s].q==0){
book=!book;
nex+=e[s].v;
}
else {
if(e[s].v<=nex && flag[s]==0)++ans,flag[s]=1;
}s+=book?nex:(-1)*nex;
++cnt;
}
cout<<ans<<endl;
return 0;
}
平衡细菌
差分好题:
一旦从差分的角度思考该问题就相当简单,
\([l,n]\)依次加n-l,n-l+1,....,n
从差分的角度,差分数组b[l+1,n]的均+1
再差分一次,差分数组c[l]++和c[n+1]--
那么题意转化成差分的形式就是,经过多少次操作后,a全部为0,同时b全部为0,也就是c全部为0
所以操作一次对c数组的影响就是c[l]++,因此答案就是c数组的总和
注意因为有可能加的也是负数,我们统计c中数值取绝对值
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+10;
int n;
int a[maxn];
int b[maxn];
int c[maxn];
signed main(){
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
int ans=0;
for(int i=1;i<=n;++i){
b[i]=a[i]-a[i-1];
c[i]=b[i]-b[i-1];
ans+=abs(c[i]);
}
cout<<ans<<endl;
return 0;
}
回文游戏
思维题
谁先取完,谁赢
首先可以知道的是0 ~ 9肯定是回文数,所以轮到一个的数字是0~9时,就赢了
对于博弈的过程,每个人都想赢,所以不会想着取一个很大回文数,因为这样结果是很随机,没有把握,所以每个人尽量选择,一个0 ~ 9的数
对于一个末尾不是0的数,那么贝尔可以选取石使得末尾为0,埃尔希就会任意选择一个不为0且不大于9的数,如此轮回,最后贝尔会使石头变为0,赢得胜利,反之埃尔希赢
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t;
int n;
string s;
void solve(){
cin>>s; if(s[s.length()-1]=='0') puts("E");
else puts("B");
return ;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
牛奶交换
最麻烦的事情,这是个环,需要特别注意
只有出现RL的时候,牛奶会在这两个捅之间循环,R左边的牛奶都会过来,L右边的牛奶也都会过来,记录每一边的牛奶,如果比时间少,那么全都损失,如果比时间多,那么只会损失时间数量的牛奶
点击查看代码
#include<bits/stdc++.h>
using namespace std;
long long n,m;
string s;
const int maxn=2e5+10;
long long a[maxn];
long long ans=0,tot=0;
int main(){
cin>>n>>m;
cin>>s;s=" "+s;
for(int i=1;i<=n;++i) cin>>a[i],tot+=a[i];
long long sum1=0,sum2=0;
bool book=0;
for(int i=1;i<n;++i){
if(s[i]=='R' && s[1+i]=='L') book=1;
if(s[i]=='L' && s[i+1]=='R') book=1;
}
if(!book){
cout<<tot<<endl;return 0;
}
for(int i=1;i<=n;++i){
if(s[i]=='R' && s[(i)%n+1]=='L'){
int j=i-1;
while(s[j]=='R'){
sum1+=a[j];
--j;
if(j==0) j=n;
}
j=i%n+2;
while(s[j]=='L' && j<=n){
sum2+=a[j];
++j;
if(j==n+1) j=1;
}
ans+=min(sum1,m)+min(sum2,m);
sum1=0,sum2=0;
}
}
cout<<tot-ans<<endl;
return 0;
}
最大限度地提高生产力
由于时间的数据范围不大,我们可以直接用后缀和预处理某个时刻之后还开着的农场,查询时就可以以O(1)的时间查询还开着的农场
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,q;
const int maxn=2e6+10;
int t[maxn],c[maxn];
int sum[maxn];
int v,s;
int main(){
cin.tie(0);cout.tie(0);
ios::sync_with_stdio(0);
memset(sum,0,sizeof(sum));
cin>>n>>q;
for(int i=1;i<=n;++i) cin>>c[i];
for(int i=1;i<=n;++i){
cin>>t[i];
if(c[i]-t[i]-1>=0)sum[c[i]-t[i]-1]++;
}
for(int i=2e6;i>=0;--i) sum[i]+=sum[i+1];
while(q--){
cin>>v>>s;
if(sum[s]>=v) puts("YES");
else puts("NO");
}
return 0;
}