寒假的训连已经接近尾声,这个寒假的主要训练就是牛客,以及队里组织的比赛还有自己参加的codeforces比赛。总的来说收获还是挺多的,对各个算法的运用和了解也加深了很多,这一周还是比较忙的,不仅打牛客上的比赛还把以前的题目补了一下,还有就是codeforces上的比赛也没有落下,还是挺忙的。牛客上的比赛有点痛苦,好多就是思路出的很快但是提交时就一直卡着,一道题提交五六次也不对,不断自己找例子代入也没办法解决,赛后补题发现要么是没有特判,要么是没有考虑特殊情况。大概是自己做题时没有想太多的缘故,也可能是训练的还是不够。开学前会把这个寒假习题尽量补全,但那种用到很复杂的算法,看半天还一知半解的习题感觉与自己水平相差甚远。就会有选择的去补。
时空的交织
这道题写的真是造孽了,明明是分别求出两个数组的最大字段和和最小字段和,然后求出相乘的最大值。我直接用dp模板复制粘贴,但没想到模板那个求的是大于零的最大字段和,我说怎么一直不对,真是粗心的想给自己一巴掌。写一下最通用的模板;
maxx=-1e9,minn=1e9;
s[100005],dp1[100005],dp2[100005];
for(int i=1;i<=n;i++){
cin>>s[i];//
dp1[i]=dp2[i]=s[i];
}
for(int i=1;i<=n;i++)
{
dp1[i]=max(dp1[i-1]+s[i],s[i]);
dp2[i]=min(dp2[i-1]+s[i],s[i]);
maxx=max(dp1[i],maxx);
minn=min(dp2[i],minn);
}
cout<<maxx<<minn;//maxx是最大字段和,minn最小字段和。
注意这里maxx求的是包含负数的最大字段和,如果有其他要求。通过修改maxx,minn的初始值来达到目的。
例如要求最大字段和必须是非负数,可以把maxx=0;根据特殊情况来进行特殊讨论。
以下是这道题代码
include <bits/stdc++.h>
define int long long
using namespace std;
int n,m;
int a[100005],b[100005];
int maxa=-1e10,mina=1e10,maxb=-1e10,minb=1e10;
int f[100005],g[100005];
void solve(){
cin >> n >> m;
for(int i=1;i<=n;i++){
cin>>a[i];
f[i]=a[i];
g[i]=a[i];
}
for(int i=1;i<=n;i++){
f[i]=max(f[i-1]+a[i],a[i]);
g[i]=min(g[i-1]+a[i],a[i]);
mina=min(mina,g[i]);
maxa=max(maxa,f[i]);
}
for(int i=1;i<=m;i++){
cin>>b[i];
f[i]=b[i];
g[i]=b[i];
}
for(int i=1;i<=m;i++){
f[i]=max(f[i-1]+b[i],b[i]);
g[i]=min(g[i-1]+b[i],b[i]);
minb=min(minb,g[i]);
maxb=max(maxb,f[i]);
}
cout<<max({maxamaxb,maxaminb,minamaxb,minaminb});
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int =1;
while(--) solve();
return 0;
}
真的要特别注意人家要你求的是哪种字段和;
爱恨的纠葛
这道题用的是二分,把两个数组排序,二分出答案;
3
2 6 4//a[i]
1 3 5//b[i]
这道题只需要会找第一个数组的每个数在第二个数组中范围是多少。
2
l=lower_bound(b+1,b+4,2-1);
r=lower_bound(b+1,b+4,2);
i=1,r=3;
6
l=lower_bound(b+1,b+4,6-1);
r=lower_bound(b+1,b+4,6);
l=r=5;
4
l=lower_bound(b+1,b+4,4-1);
r=lower_bound(b+1,b+4,4);
l=3,r=5;
设一个结果ans
ans=min({abs(a[i]-l),abs(a[i]-r),ans});
ans就是最小值;
include<bits/stdc++.h>
define int long long
using namespace std;
int n,s[100005],q[100005],d[100005];
void solve(){
for(int i=1;i<=n;i++)
cin>>s[i];
for(int i=1;i<=n;i++){
cin>>q[i];
d[i]=q[i];
}
sort(s+1,s+n+1);
sort(d+1,d+n+1);
int minn=1e9,vis=0,vi=0;
for(int i=1;i<=n;i++){
int sum=lower_bound(d+1,d+n+1,s[i]-1);
if(minn>=abs(sum-s[i])){
minn=abs(sum-s[i]);
vis=sum;
vi=s[i];
//cout<<vis<<' ';
}
sum=lower_bound(d+1,d+n+1,s[i]);
if(minn>=abs(sum-s[i])){
minn=abs(sum-s[i]);
vis=sum;
vi=s[i];
}
}
int y=0,u=0;
for(int i=1;i<=n;i++){
if(q[i]vis){
y=i;
break;
}
}
for(int i=1;i<=n;i++){
if(s[i]vi){
u=i;
break;
}
}
int t=s[y];
s[y]=s[u];
s[u]=t;
for(int i=1;i<=n;i++)
cout<<s[i]<<' ';
}
signed main(){
cin>>n;
solve();
}
心绪的解剖
这道题有点像把数分解为质数相加那一题
先用vector存储斐波那契数
void df(){
ve.emplace_back(0);
ve.emplace_back(1);
for(int i=2;i<=50;i++)
{
int t=ve[i-1]+ve[i-2];
ve.emplace_back(t);
}
}
斐波那契数到45时就已经达到1e9了
然后用暴力vector求最大小于 m的数,m-=vector[i];
遍历三次,用a,b,c存储结果
for(int i=0;i<=45;i++){
if(ve[i]>m){
a=ve[i-1];
m-=ve[i-1];
break;
}
}
for(int i=0;i<=45;i++){
if(ve[i]>m){
b=ve[i-1];
m-=ve[i-1];
break;
}
}
for(int i=0;i<=45;i++){
if(ve[i]>m){
c=ve[i-1];
m-=ve[i-1];
break;
}
}
if(m==0){
cout<<a<<' '<<b<<' '<<c<<'\n';
}
else
cout<<"-1\n";
}
}
标签:ve,minn,int,sum,bound,100005,第五,周报 From: https://www.cnblogs.com/niubuniu/p/18032262