2024/3/12

本文介绍了如何在给定有序数组中插入特定元素以最小化相邻项差值,使用了二分法策略。同时,也讨论了解决另一个问题——在全排列中找到最长不被整除的子序列的简单方法。
摘要由CSDN通过智能技术生成
F. Rudolf and Imbalance

原题链接:Problem - F - Codeforces

题目大意:

给n,m,k三个整数

然后输入长度分别为n,m,k的三个整数数组a,d,f。然后a数组是有序递增的,问你往a数组中插入一个d[i]+f[j]使得a数组中的相邻两项的差的最大值最小化,还可以不插入,插入一个或者不插入,使得a数组中的相邻两项的差的最大值最小化。

题目做法:

插入一次只能改变一个相邻两项差,要使得影响最大,显然想到往原本差最大的两项中间差,且插入的值越接近两项的中央越好,好平的思路的F,接下来就是代码实现了。用二分去找这个最接近中央的值。时间复杂度 m\log k,显然没问题。

AC代码:

#include<bits/stdc++.h>
#define pb(element) push_back(element)
#define fast ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
using namespace std;
const int maxn=1e5+100;
void solve()
{
    int n,m,k;
    set<int> ss;
    cin>>n>>m>>k;
    int a[n],d[m],f[k+1],large,seclarge;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<m;i++) cin>>d[i];
    for(int i=0;i<k;i++) cin>>f[i];
    sort(d,d+m);
    sort(f,f+k);
    f[k]=1e17;
    int ps=0;
    map<int,int> mp;
    for(int i=0;i<n-1;i++)
    {
        ss.insert(abs(a[i+1]-a[i]));
        mp[abs(a[i+1]-a[i])]++;
        if(abs(a[i+1]-a[i])>=abs(a[ps+1]-a[ps]))
        {
            ps=i;
        }
    }
    auto its=ss.end();
    its--;
    if(ss.size()==1)
    {
        seclarge=large=*its;
    }
    else
    {
        large=*its;
        its--;
        seclarge=*its;
    }
    if(mp[abs(a[ps+1]-a[ps])]!=1)
    {
        cout<<abs(a[ps+1]-a[ps])<<'\n';
    }
    else
    {
        int go=(a[ps+1]+a[ps])/2,di=d[0]+f[0];
        for(int i=0;i<m;i++)
        {
            int div1,div2;
            if(d[i]>=go) div1=d[i]+f[0],div2=d[i]+f[0];
            else
            {
                int inips=lower_bound(f,f+k+1,go-d[i])-f;
                div1=d[i]+f[inips];
                div2=d[i]+f[inips];
                if(inips!=0) div2=d[i]+f[inips-1];
            }
            if(abs(div2-go)<abs(di-go))
            {
                di=div2;
            }
            if(abs(div1-go)<abs(di-go))
            {
                di=div1;
            }
        }
        go=(a[ps+1]+a[ps])/2+1;
        int div=d[0]+f[0];
        for(int i=0;i<m;i++)
        {
            int div1,div2;
            if(d[i]>=go) div1=d[i]+f[0],div2=d[i]+f[0];
            else
            {
                int inips=lower_bound(f,f+k+1,go-d[i])-f;
                div1=d[i]+f[inips];
                div2=d[i]+f[inips];
                if(inips!=0) div2=d[i]+f[inips-1];
                //cout<<div1<<" "<<div2<<'\n';
            }
            if(abs(div2-go)<abs(div-go))
            {
                div=div2;
            }
            if(abs(div1-go)<abs(div-go))
            {
                div=div1;
            }
        }
        
        int modidif=min(max(abs(a[ps+1]-div),abs(a[ps]-div)),max(abs(a[ps+1]-di),abs(a[ps]-di)));
        //cout<<modidif<<" "<<di<<'\n';
        if(seclarge!=large) cout<<max({min(modidif,large),seclarge})<<'\n';
        else cout<<max({min(modidif,large)})<<'\n';
    }
}
signed main()
{
    fast int casen=1;
    cin>>casen;
    while(casen--) solve();
}
A. XXXXX

原题链接:https://codeforces.com/contest/1364/problem/A

题目大意:

给一个数组,问最长的subarry其和不被x整除,问这个最长的subarry的长度。

题目做法:

很平的思路,如果本身总和就满足,则输出,如果不满足,其中所有元素都被x整除则为-1。

剩余情况就是从头或者尾开始,删到第一关不被x整除的数为止,要求删得尽量少。

AC代码:

def solve():
    n, x = map(int, input().split())
    ar = list(map(int, input().split()))
    sum = 0
    flag = 0
    for i in ar:
        sum += i
        if(i % x != 0): flag = 1
    if(sum % x != 0): print(n)
    elif(sum % x == 0 and flag == 0): print("-1")
    else:
        front = 0
        back = 0
        for i in range(0, n):
            if(ar[i] % x != 0):
                front = i
                break
        for i in range(n-1, -1, -1):
            if(ar[i] % x != 0):
                back = i
                break
        # print(n, front, n - front - 1, back)
        print(max(n - front - 1, back))
casen = int(input())
for i in range(0, casen): solve()

啥时候我的python也能像c++一样熟练啊。。。。。

B. Most socially-distanced subsequence

原题链接:Problem - B - Codeforces

题目大意:

有一个全排列,要求你从其中选取一个subsequence满足如下条件

题目做法:

只有峰值需要被考虑,峰值到峰值间的数影响会被峰值覆盖。

比A还简单,就是我python真的,我真不想学python吧。。。。。

AC代码:

def solve():
    n = int(input())
    ar = list(map(int, input().split()))
    res = []
    res.append(ar[0])
    if(ar[0] > ar[0 + 1]): up = 1
    else: up = 0
    for i in range(1, n - 1):
        if(ar[i] > ar[i + 1]):
            if(up == 0): res.append(ar[i])
            up = 1
        else:
            if(up == 1): res.append(ar[i])
            up = 0
    res.append(ar[n - 1])
    print(len(res))
    for i in res:
        print(i,end = ' ')
    print('\n')
casen = int(input())
for i in range(0, casen): solve()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值