2024 暑假友谊赛-热身1

b.Linear Approximation - AtCoder arc100_a - Virtual Judge

思路:数学或者三分,一开始用的三分,没解出来,在这里解一下

代码:

#include<bits/stdc++.h>
#define FIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef long double ld;
void test_case()
{
    ll n;
    cin>>n;
    ll a[n];
    ll mx=0;
    for(int i=0;i<n;i++)cin>>a[i],mx=max(mx,a[i]);
    ll low=-1e12,high=1e12;
    ll ans=4e18;
    for(int i=0;i<=300;i++)//由于pow(2,300)大于了2e12,所以必定能把这两个区间搜完
    {
        ll m1=low+(high-low)/3;
        ll m2=high-(high-low)/3;
        ll fm1=0;
        ll fm2=0;
        for(int j=0;j<n;j++)fm1+=abs(a[j]-(m1+j+1));
        for(int j=0;j<n;j++)fm2+=abs(a[j]-(m2+j+1));
        ans=min(ans,fm1);
        ans=min(ans,fm2);//过程中记录了最小值
        if(fm1<fm2)high=m2-1;
        else low=m1+1;
    }
    cout<<ans;

}
int main()
{
    FIO
    int t;
    t=1;
//    cin>>t;
    while(t--)
    {
        test_case();
    }
}

d.AtCoder arc100_b

思路:带一点三分的思想,定义第一个区间范围为 1 − i ;第二个区间范围为 i − j ;第三个区间范围为 j − k ;第四个区间范围为 k − n 

我们枚举 j  从 2至 ( n − 1 ) ,那 i和 k  一定是把 1 − ( j − 1 ) ,j − n 这两个区间分最点的点。

这种方法的时间复杂度是 O ( n ) 不会超时。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
#define int long long
int a[maxn];
int sum[maxn];
signed main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
    }
    int ans=2100000000;
    for(int i=1,j=2,k=3;j<n;j++){
        while(i+1<j&&abs(sum[j]-2*sum[i])>abs(sum[j]-2*sum[i+1]))i++;
        while(k+1<n&&abs(sum[n]-2*sum[k]+sum[j])>abs(sum[n]-2*sum[k+1]+sum[j]))k++;
        ans=min(ans,max({sum[i],sum[j]-sum[i],sum[k]-sum[j],sum[n]-sum[k]})-min({sum[i],sum[j]-sum[i],sum[k]-sum[j],sum[n]-sum[k]}));
    }
    cout<<ans;
}

e.Unlucky Numbers - CodeForces 1808C - Virtual Judge

题解:可以考虑暴力枚举这个数里最大的数位(y)和最小的数位(x),然后只需要判断只使用 [x,y]内组成的数是否有存在在 [l,r]内的。
一种做法就是数位 dp,分别限制一下上下界或者差分一下判断数量,但是这太麻烦了。
我们其实可以考虑直接用 [x,y]组成大于等于 l𝑙 的最小的数,如果这个数小于等于 r𝑟 则证明有解。
这个解法很显然是正确的。

fAir Conditioners - CodeForces 1547E - Virtual Judge

思路:由于i位置的温度必定与相邻两个位置的其中一个温度具有连续性,一开始考虑到给出的空调点中某些位置是无效的,并且,空调的温度会向两边扩展,每一个点的温度由该点是否有空调,左侧空调和右侧空调影响,所以我们可以从最左端往右,最右端往左更新取最小值(也就题目描述可能复杂一些)

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=110,M=3e5+10;
#define PII pair<int,int>
int n,k;
int a[M];
int b[M];
void solve(){
    cin>>n>>k;
    int minn=1000000;
    int maxn=0;
//    初始化
    memset(b,0x3f,sizeof b);
    for(int i=1;i<=k;i++) {
        cin >> a[i];
        minn=min(minn,a[i]);
        maxn=max(maxn,a[i]);
    }
    //状态1⃣️
    for(int i=1;i<=k;i++){
        cin>>b[a[i]];
    }
    //状态2⃣️从前往后依次遍历
    for(int i=minn+1;i<=n;i++){
        b[i]=min(b[i],b[i-1]+1);
    }
    //状态3⃣️从后往前更新状态
    for(int i=maxn-1;i>=1;i--){
        b[i]=min(b[i],b[i+1]+1);
    }
    for(int i=1;i<=n;i++) cout<<b[i]<<" ";
    cout<<endl;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin>>t;
    while (t--) {
        solve();
    }
    return 0;
}

gBrutality - CodeForces 1107C - Virtual Judge

思路:连续字母区间取最前k大的值就好

代码:


#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
int n,k;
int a[200010];
bool cmp(int x,int y){
    return x>y;
}
void solve()
{
    cin>>n>>k;
    int res=0;
    for(int i=0;i<n;i++) cin>>a[i];
    string s;
    cin>>s;
    for(int i=0;i<n;){
        int b[200010];
        int j=i;
        int tt=0;
        while(s[j]==s[i]&&j<n){
            b[tt++]=a[j];
            j++;
        }
        sort(b,b+tt,cmp);
        int cnt=0;
//        cout<<tt<<endl;
        for(int l=0;l<tt;l++){
//            cout<<b[l]<<" ";
            if(cnt>=k) break;
            res+=b[l];
            cnt++;
        }
        i=j;
    }
    cout<<res<<endl;

}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
//    cin>>t;
    while (t--) {
        solve();
    }
    return 0;
}

*hAll Your Paths are Different Lengths - AtCoder arc102_b - Virtual Judge

思路:那年我双手插兜,不知道该往哪里走

*iConstrained Nim 2 - AtCoder abc297_g - Virtual Judge

思路:太难了,放过鼠鼠吧。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值