前言
也是好久没有打div4了,上一次还是半年前的第二场cf比赛,记得当时过了3题,非常开心。这一次过了5个题,D题调试时间太久,导致F题最后没时间调试了。总之还不错。
Codeforces Round #835(div4)补题链接
A. Medium Number 签到
题意:给你三个数,求中位数。
Acwing周赛原题,写个数组,排序一下,然后输出中间即可。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--){
int a[3];
cin>>a[0]>>a[1]>>a[2];
sort(a,a+3);
cout<<a[1]<<endl;
}
return 0;
}
B Atilla’s Favorite Problem 签到
题意:给你一个字符串,找到ASCII码最大的字符。输出字母表中的位置。
思路:直接暴力扫一遍,更新最大值即可,记得下标需要+1。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--){
int n;
cin>>n;
string s;
cin>>s;
int ans=0;
for(int i=0;i<n;i++){
ans=max(ans,s[i]-'a'+1);
}
cout<<ans<<endl;
}
return 0;
}
C. Advantage 签到
题意:给定一串序列,求出每个序列与除他以外最大的值得差值。
思路:求出最大值和次大值。对于不等于最大值的,直接用它减去最大值,反之,减去次大值。
最大值和次大值可以维护,我就直接备份了一个数组,然后直接排序求了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
int T;
cin>>T;
while(T--){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b,b+n);
for(int i=0;i<n;i++){
if(a[i]!=b[n-1]) cout<<a[i]-b[n-1]<<" ";
else cout<<a[i]-b[n-2]<<" ";
}
cout<<endl;
}
return 0;
}
D. Challenging Valleys 思维
题意:如果一段序列只存在一段“谷”,那么输出“Yes”,否则输出“No”。所谓“谷”,要么首段上升,要么尾端下降,或者先下降,在上升。
思路:因为只能有一个“谷”出现,我们发现,如果序列上升了,那么就必须一直上升,否则就会存在多个“谷”。(因为你上升了然后又下降,只有两种情况,一种一直下降到最后,那么就会有首端和尾端两个谷,不满足题意,如果你上升下降后面又上升,那么就有首段一个谷,下降上升又一个谷,两个谷,不满足题意)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N =2e5+10;
int a[N];
int main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
bool flg=0;//表示是否已经上升过
bool ans=0;
for(int i=1;i<n;i++){
if(a[i]>a[i-1]) flg=1;
if(flg&&a[i]<a[i-1]) {ans=1;break;}
}
if(ans) puts("No");
else puts("Yes");
}
return 0;
}
E. Binary Inversions 思维+贪心
题意:给你一个只含0和1的数组,你有一次机会把一个数反转(0变为1,1变为0),让你求出各种操作后逆序对的最大值。
思路:因为数组比较特殊,只含0和1,那么逆序对数量就等于,每个1后面0的数量之和。这里可以贪心,如果要使逆序对最大,那么我们可以把第一个0改为1,或者把最后一个1改为0,最后计算原本的逆序对,三个取最大值即可。
写一个求解逆序对函数,倒着统计0的个数,如果遇到1,那么这个1的逆序对数就是当前0的数量,总逆序对,求个和就好。记得开long long。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N =2e5+10;
typedef long long LL;
LL a[N],cnt[N];
int n;
LL Reverse_pair(){
memset(cnt,0,sizeof cnt);//数组初始化
LL res=0,num=0;
for(int i=n;i>=1;i--){
if(!a[i]) num++;
else cnt[i]=num;
}
for(int i=1;i<=n;i++){
res+=cnt[i];
}
return res;
}
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--){
cin>>n;
bool flg=0;
int f0=0,l1=0;//维护第一个0和最后一个1的下标
for(int i=1;i<=n;i++) {cin>>a[i];
if(!flg&&!a[i]) {f0=i;flg=1;}
if(a[i]) l1=i;
}
LL b=Reverse_pair();
a[f0]=1;//第一个0变为1
LL c=Reverse_pair();
a[f0]=0;//还原
a[l1]=0; //最后一个1变为0
LL d=Reverse_pair();
cout<<max({b,c,d})<<endl;
}
return 0;
}
F. Quests 前缀和+二分
题意:给你n个任务,每个任务做完,会给你ai的奖励,任务做完后k天就不能再做这个任务,给你c和d,让你求出能够在d天内,奖励达到c的最大k值。
分析:因为我们需要尽快达到c,所以每次先做奖励最多的任务,所以需要排个序,二分答案,mid为一个周期,一个周期之后就可以在做奖励最多的任务。所以check函数就写当前的奖励是否大于等于c即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long LL;
LL a[N],sum[N];
LL n,c,d;
bool check(LL mid){
LL res=sum[min(mid+1,n)]*(d/(mid+1))+sum[min(n,d%(mid+1))];
return res>=c;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>n>>c>>d;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1,greater<int>());
memset(sum,0,sizeof sum);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
LL l=-1,r=d+1;
while(l<r){
LL mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
if(l==-1) puts("Impossible");
else if(l==d+1) puts("Infinity");
else cout<<l<<endl;
}
}
G. SlavicG’s Favorite Problem 图论+搜索+思维
题意:给你一棵带边权的树,给定起点a和终点b,刚开始的分数是0,每次经过一条边,分数就等于当前分数异或上该边的边权,要求你最后到大b时,分数要为0,你在图中有一次可以传送的机会,你可以传送到任意结点,求是否可以满足要求。
思路:根据异或的性质,两个相同的分数异或,结果为0,所以我们可以从起点搜索一遍,记录下经过每一条边当前的分数。在从终点相同方式搜索一遍,如果遇到了相同的分数,那么我们可以到达一个相同的节点,然后传送到另一个值相等的节点,再走到b即可满足条件,否则,无法满足条件。
代码:多组数据,记得做好中间变量初始化操作。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=2*N;
int h[N],e[M],ne[M],w[M],idx;
int n,a,b;
bool st[N];
bool flg;
map<int,int> mp;
void add(int a,int b,int c){
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
void init(){//变量初始化
idx=0;
flg=0;
memset(h,-1,sizeof h);
memset(e,0,sizeof e);
memset(ne,0,sizeof ne);
memset(w,0,sizeof w);
memset(st,0,sizeof st);
mp.clear();
}
void dfs(int u,int cur){
mp[cur]=1;
st[u]=true;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(st[j]) continue;
if(j==b) continue;
dfs(j,cur^w[i]);
}
}
void dfs1(int u,int cur){
st[u]=true;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(st[j]) continue;
dfs1(j,cur^w[i]);
if(flg) return;
if(mp[cur^w[i]]) flg=1;
}
}
int main(){
int T;
cin>>T;
while(T--){
cin>>n>>a>>b;
init();
n--;
while(n--){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
dfs(a,0);
memset(st,0,sizeof st);
dfs1(b,0);
if(flg) puts("YES");
else puts("NO");
}
}