欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > CF每日5题(1300-1500)

CF每日5题(1300-1500)

2025/5/24 13:55:13 来源:https://blog.csdn.net/2301_79881289/article/details/148027312  浏览:    关键词:CF每日5题(1300-1500)

1971E 模拟 1500

思路很简单 d在 a l a_l al a r a_r ar之间 d − a l t − b l = a r − a l b r − b l {{d-a_l}\over{t-b_l}}={{a_r-a_l}\over{b_r-b_l}} tbldal=brblaral
lower_bound 找第一个大于等于d的 a i a_i ai

void solve()
{int n,k,q;cin>>n>>k>>q;vector<int>a(k+1,0),b(k+1,0);vector<int>dis(k+1),t(k+1);forr(i,1,k){cin>>a[i];dis[i-1]=a[i]-a[i-1];}// for(auto i:a)cout<<i<<' ';cout<<endl;// forr(i,0,k)cout<<dis[i]<<' ';cout<<endl;forr(i,1,k){cin>>b[i];t[i-1]=b[i]-b[i-1];}while (q--){int d;cin>>d;int id=lower_bound(a.begin()+1,a.end(),d)-a.begin();// cout<<id<<endl;// cout<<id<<' '<<a[id]<<' '<<dis[id]<<endl;int ans=b[id-1]+(d-a[id-1])*t[id-1]/dis[id-1];cout<<ans<<' ';}cout<<endl;
}

(这是1500的题?

1974C 暴力 容斥原理 1400

一开始还以为n-2个三元组里面有什么规律…看了题解恍然大悟,可以开桶计数,时间复杂度O(nlogn),不会超时

  • 统计13、23、12位置数字相同的三元组个数a、b、c,但是123位置都相同的也包含在a、b、c中,他们不是美丽的,要除去
  • 统计123位置都相同的个数d
  • 每个三元组贡献a+b+c-3*d

dalao的题解中用了三元组turple 二元组pair

struct gr1{int a,b;bool operator<(const gr1 &x)const{return (a==x.a?b<x.b:a<x.a);}
};
struct gr2{int a,b,c;bool operator<(const gr2 &x)const{return (a==x.a?(b==x.b?c<x.c:b<x.b):a<x.a);}
};
void solve()
{int n;cin>>n;vector<int>a(n+1,0);//b1:12相同 b2:23 b3:13map<gr1,int>b1,b2,b3;map<gr2,int>b4;forr(i,1,n)cin>>a[i];int ans=0;for(int i=1;i<=n-2;i++){// cout<<a[i]<<' '<<a[i+1]<<' '<<a[i+2]<<endl;ans+=b1[{a[i],a[i+1]}];ans+=b2[{a[i+1],a[i+2]}];ans+=b3[{a[i],a[i+2]}];ans-=b4[{a[i],a[i+1],a[i+2]}]*3;b1[{a[i],a[i+1]}]++;b2[{a[i+1],a[i+2]}]++;b3[{a[i],a[i+2]}]++;b4[{a[i],a[i+1],a[i+2]}]++;}cout<<ans<<endl;
}

1980D 思维 枚举 1400

一开始有找到递减位置进行处理的思路,但是不知道如果有多个位置怎么去判断。
参考dalao题解
a[1:n] 找出的gcd数组b[1:n-1]

  • 从前后分别找出数组b一直递增的最大位置
  • 如果没有递减的位置,l=n-1 r=1
  • 如果递减的位置在边上,l=n-2或r=2
  • 其他情况就枚举a中a[i]被删去,b中对应b[i]和b[i-1]也寄了,变成gcd(a[i-1],a[i+1])
const int N=1e18+10;//一开始无穷大开小了 一直wa
void solve()
{int n;cin>>n;vector<int>a(n+2),b(n+1);forr(i,1,n)cin>>a[i];a[n+1]=a[0]=0; forr(i,1,n-1)b[i]=__gcd(a[i],a[i+1]);b[n]=N;b[0]=0;int l=1,r=n;while (l<=n-2&&b[l]<=b[l+1])l++;//从前面开始记录降序的位置while (r>=2&&b[r-1]<=b[r])r--;// cout<<l<<' '<<r<<endl;if(l==n||r==0)return cout<<"yes"<<endl,void();if(l==n-2||r==2)return cout<<"yes"<<endl,void();//判断边上有没有递减的forr(i,1,n){//枚举每一个数被删去的情况int ng=__gcd(a[i-1],a[i+1]);if(ng>=b[max(i-2,0ll)]&&ng<=b[min(i+1,n)]&&l>=i-2&&r<=i+1){//看能不能和前后接上return cout<<"yes"<<endl,void();}}return cout<<"no"<<endl,void();}

1996D 枚举 数学 1500

参考dalao题解
三元组顺序不同属于不同答案,考虑枚举a,b
c ≤ n − a b a + b , c ≤ x − a − b c\leq {{n-ab}\over{a+b}},c\leq{x-a-b} ca+bnab,cxab

问题在于时间复杂度会不会超时
ab的要求是 a + b ≤ x , a b + ( a + b ) ≤ n ( 因为 c ≥ 1 ) a+b\leq x,ab+(a+b)\leq n(因为c\geq1) a+bx,ab+(a+b)n(因为c1)
那么 a b ≤ n , b ≤ n a ab\leq n,b\leq {n\over a} abn,ban
运行次数就是 n ∑ 1 x 1 a n\sum\limits_{1}^{x}{1\over a} n1xa1 调和级数求和是ln级别,不会超时

void solve()
{int n,x;cin>>n>>x;int ans=0;forr(a,1,x){forr(b,1,x){if(a*b+(a+b)>n)break;int c=max(0ll,min((n-a*b)/(a+b),x-(b+a)));ans+=c;}}cout<<ans<<endl;
}

2106D 贪心 思维 1500

dalao的神奇题解
题意:从左向右,在数组a中选取 a j ≤ b i a_j\leq b_i ajbi,如果不够可以使用一次机会在a中,添加一个数k能把b选满,求k最小值
分析:
选取的花有要求

  • a j ≤ b i a_j\leq b_i ajbi
  • 下标递增

题解中题意转化成b的删数很神奇

来自dalao题解
在这里插入图片描述

  • 每次贪心地选取,一遇到 a j ≤ b i a_j\leq b_i ajbi就记录a的下标
  • 下标递增,从左向右和从右向左遍历+贪心都能形成,区别在于每次选取最靠左还是最靠右的数
    对某个 b i b_i bi b i − 1 b_{i-1} bi1最靠左的数下标< b i + 1 b_{i+1} bi+1最靠右的数下标,那么在 b i b_i bi两边能形成递增的下标, k = b i k=b_i k=bi可以添加在这之间
void solve()
{int n,m;cin>>n>>m;vector<int>a(n+1),b(m+1),pi(m+1,n+1),si(m+1,0);//从左向右找pi记录 从右向左siforr(i,1,n)cin>>a[i];forr(i,1,m)cin>>b[i];for(int bi=1,j=1;bi<=m&&j<=n;bi++,j++){while(j<=n&&b[bi]>a[j])j++;pi[bi]=j;//记录从左往右找的位置}if(pi[m]!=n+1)return cout<<0<<endl,void();for(int bi=m,j=n;bi>=1&&j>=1;bi--,j--){while(j>=1&&b[bi]>a[j])j--;si[bi]=j;}pi[0]=0,si[m+1]=n+1;int ans=1e9+10;forr(i,1,m){if(pi[i-1]<si[i+1])ans=min(ans,b[i]);}if(ans==1e9+10)return cout<<-1<<endl,void();else cout<<ans<<endl;
}

热搜词