前言:昨晚cf卡的不行,镜像的页面也打不开,卡爆了,硬着头皮打了一个小时,给卡红温了。 据说比上次的div3还难(我也看不出来),一小时后,官方说明本次unrated,直接睡觉去了,只A了ABD,cwa了三发没做出来。
今天也是补到F题了,把题解写一写---2024.9.4
A.Minimize!
赛后发现直接算就行了,c可以抵消掉,直接输出b-a,当时还傻傻地遍历。。。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve()
{
int a,b;
cin>>a>>b;
int op = INT_MAX;
for(int i=a;i<=b;i++){
op = min(op,i-a+b-i);
}
cout<<op<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}
B. osu!mania
直接存入矩阵点,然后从大到小遍历输出#第一次出现地位置
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve()
{
int n;
cin>>n;
char a[n+1][5];
for(int i=1;i<=n;i++){
for(int j=1;j<=4;j++){
cin>>a[i][j];
}
}
for(int i=n;i>=1;i--){
for(int j=1;j<=4;j++){
if(a[i][j]=='#'){
cout<<j<<" ";
break;
}
}
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}
C. The Legend of Freya the Frog
关键在于出发顺序,这里被坑了好几发罚时,可以提前计算出向x和向y所走的步数。
如果x所需的步数大,在x走完之前,y肯定已经达到,x走完最后一步,y就不用走了,所以是2*x-1;
如果是y较大或者相等,则必须走完x再走y,所有结果为2*y
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve()
{
LL x,y,k;
cin>>x>>y>>k;
if(x==0 && y==0){
cout<<0<<endl;
return;
}
LL xx = x/k+(x%k!=0);
LL yy = y/k+(y%k!=0);
if(xx>yy){
cout<<LL(xx*2)-1<<endl;
}
else{
cout<<LL(yy*2)<<endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}
D. Satyam and Counting
题目乍一看很复杂,n个点取三个凑成三角形,其实限定y的高度不是0或者1,样例也给出了提示。
一共两种情况:
一个点,如果其对面的两个相邻的点存在,则是一个三角形。
另外就是上下点都存在,则其他点必然凑成三角形。
考虑遍历求解即可,注意边界,这里卡时间复杂度。(赛后边界给我重测wa了!!!)
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve()
{
int n;
cin>>n;
vector<vector<int> > a(n+1,vector<int>(2,0));
int l =0,r= 0;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
a[x][y]=1;
if(y==0) r++;else l++;
}
LL ans = 0;
for(int i=0;i<=n;i++){
if(a[i][0]==1 && a[i][1]==1){
ans = ans + r+l -2;
}
if(a[i][0]==1 && i>0 && i<n){
if(a[i-1][1]==1 && a[i+1][1]==1) ans++;
}
if(a[i][1]==1 && i>0 && i<n){
if(a[i-1][0]==1 && a[i+1][0]==1) ans++;
}
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}
E. Klee's SUPER DUPER LARGE Array!!!
给出一个数,表示成一个数组,以给出的数开头,ai+1与ai相隔1,在数组中选定一个i值,取i前数字的和和i后的合做差的绝对值,求绝对值的最小值,(即最接近0)
取的i值从右往左,逐渐递增,最终一定会有大于0和小于0的边界点,考虑二分求解
最后求出的l值不一定是最小,根据check函数模拟一下,可得l-1也有可能,计算取一个min值即可
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
void solve()
{
LL n,k;
cin>>n>>k;
LL l = k , r = k+n-1;
function<LL(LL)> check = [&](LL x) -> LL{
LL res = 0;
LL nn = x-k+1;
LL pre = nn*(k)+(nn*(nn-1))/2;
LL sub = (n-nn)*(k+nn)+(n-nn)*(n-nn-1)/2;
// cout<<pre<<" "<<sub<<" ";
res = pre - sub;
return res;
};
while(l<r){
LL mid = (l+r)/2;
if(check(mid)>=0) r =mid;
else l =mid + 1;
}
if(abs(check(l-1))<=abs(check(l))){
l = l-1;
}
cout<<abs(check(l))<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}
F. Firefly's Queries
这题花了不少时间,但其实思路很简单,还是练少了,注意用64位使用unsigned long long
以每n次进入一个循环,而每个前n项的总和是不变的,变的是多出来的一部分在原数组中的起始值,起始值到n可能会不够减去,考虑用后缀和前缀一起维护,分类讨论即可
#include <bits/stdc++.h>
using namespace std;
using LL = unsigned long long;
void solve()
{
int n,q;
cin>>n>>q;
vector<LL> a(n+1,0),pre(n+1,0),sub(n+1,0);
LL sum = 0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
pre[i] = pre[i-1] +a[i];
}
sub[n] = a[n];
for(int i=n - 1;i>=1;i--){
sub[i] = sub[i+1] + a[i];
}
while(q--){
LL l,r;
cin>>l>>r;
l--;
LL num1 = (r/n)*sum;
LL num2 = (l/n)*sum;
LL i = r/n + 1;
LL j = l/n + 1;
l%=n; r%=n;
// cout<<num1<<" ";
if(n-i+1<r){
num1 += sub[i] + pre[r-n+i-1];
}
else{
num1+= pre[i+r-1] - pre[i-1];
// cout<<pre[i+r-1]<<" "<<pre[i-1]<<" ";
}
if(n-j+1<l){
num2 += sub[j] + pre[l-n+j-1];
}
else{
num2+= pre[j+l-1] - pre[j-1];
// cout<<pre[i+r-1]<<" "<<pre[i-1]<<" ";
}
cout<<LL(num1-num2)<<endl;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t ;
cin>>t;
while (t--)
{
solve();
}
}