周赛补题yy

一.水题(双指针)

传送门

题意:给一n个数:a1,a2,a3,...,an 同时进行判断两头数是否相等若相等则删除数ai,即前q个数若是等于后w个数就删除这(q+w)个数。

利用双指针进行遍历(ps:我是真的菜)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#define Ios ios::sync_with_stdio(0);cin.tie();cout.tie();
#define INF 0x3f3f3f
#define mod 1000000009
using namespace std;
typedef long long ll;
const int N=2e5+9;
int a[N];
int main()
{
    Ios
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        ll sum=0;
        ll ans=0;
        for(int i=1,j=n;i<=j;)
        {
            if(sum>0){sum-=a[j];j--;}
            else {
                sum+=a[i];i++;
            }
            
            if(sum==0){ans=i+n-j-1;}
        }
        
        printf("%d\n",ans);
    }
    return 0;
}
//一个while也可以
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#define Ios ios::sync_with_stdio(0);cin.tie();cout.tie();
#define INF 0x3f3f3f
#define mod 1000000009
using namespace std;
typedef long long ll;
const int N=2e5+9;
int a[N];
void slove()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int ans=0;
    int sum1=a[1];int sum2=a[n];
    int l=1;int r=n;
    while(l<r)
    {
        if(sum1==sum2)
        {
            ans=max(ans,n-r+1+l);
        }
        if(sum1<=sum2)
        {
            sum1+=a[++l];
        }
        if(sum1>sum2){
            sum2+=a[--r];
        }
    }cout<<ans<<endl;
}
int main()
{
    Ios
    int T;
    cin>>T;
    while(T--)
    {
        slove();
    }
    
    return 0;
}

二.兔子(思维)

传送门

题意:

在一个长度为n的迷宫中有一个兔子,兔子每次可以往左或者往右跑,每次你可以检查某一个洞里是否有兔子。请问在最坏情况下,最少需要多少次必定能够找到这只兔子。

分析:

比较抽象的一道题,显然我们需要从某一方向一个一个找过去。但是可能存在一种情况,我们在i位置,兔子在i + 1位置,此时我们检查完i下一步去i + 1检查,此时兔子就跑到i位置去了,也就是错过。显然我们在最坏的情况下一定会错过。什么时候会错过呢?也就是我们和兔子的距离为奇数的时候,也就是我们所在位置的奇偶和兔子是相反的时候,我们就会错过这只兔子。加入我们从1开始找到n发现都没有兔子,就可以判断出我们和兔子的奇偶性相反,我们只需要在任何一个位置随便检查一次,这样奇偶性就和兔子相同,再从n找一遍兔子,这样一定能够找到。

但是这样的次数是2n + 1,能不能再少一点呢?我们发现,既然我们可以默认第一次和兔子的奇偶性一定相反,那我们干脆放弃第一格。我们从第二格子开始检查,检查到n-1格,如果和兔子的奇偶性相同,兔子一定会被逼到n - 1的位置。因此我们也不需要在n处检查。

我们在n - 1处再检查一次,这样就保证了和兔子的奇偶性相同,接下来顺次检查回第二个格子即可。(摘抄大佬题解🙏🙏)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define Ios ios::sync_with_stdio(0);cin.tie();cout.tie();
#define INF 0x3f3f3f
#define mod 1000000009
using namespace std;
typedef long long ll;
const int N=2e5+9;
int main()
{
    Ios
    int n;
    cin>>n;
    if(n==1){printf("1\n1");}
    else if(n==2)
    {
        printf("2\n2 2");
    }else{
        cout<<2*(n-2)<<endl;
        for(int i=2;i<=n-1;i++) cout<<i<<" ";
        for(int i=n-1;i>=2;i--) cout<<i<<" ";
        
    }
    return 0;
}

三.思维(dp?)

传送门

题意:给一个容量n,接下来给9个数: a1,a2,...,a9刚开始x为0.然后在9个数中选择ai,每选择一次n要减去ai,此时x变为x*10+i,然后再次进行选择直到n不能选为止,即n要小与a中最小的数。最后要达到x的值最大。

分析:刚开时觉得跟dp有关(我还是个dp菜鸟),但实际就是个思维题。。。。。首先要想x最大肯定是先让x的位数最大,就是选数的次数最多(每选一次数,x的位数加一)然后在次数最多的前提下,选择使x最大的值就行。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#define Ios ios::sync_with_stdio(0);cin.tie();cout.tie();
#define INF 0x3f3f3f
#define mod 1000000009
using namespace std;
typedef long long ll;
const int N=2e7+9;
int a[N];
int ans[N];
int main()
{
    Ios
    int n;
    cin>>n;
    int minn=10000000;
    int m=0;
    for(int i=1;i<=9;i++)
    {
        cin>>a[i];
        minn=min(minn,a[i]);
    }
    int q=n/minn;
    for(int i=1;i<=q;i++)
    {
        for(int j=9;j>=1;j--)
        {
            if((n-a[j])>=(q-i)*minn)//注意判断条件n的范围
            {
                printf("%d",j);
                n-=a[j];
                break;
            }
        }
    }
    
    return 0;
}

四.D - Cutting Woods(set容器+二分)

传送门

题意:一根长为L米的木头,进行Q次操作,每次操作分为两类:操作一:输入x在x处砍断。操作二:输入x,判断x米处所在的木头有几米,输出长度。(被砍断的地方不会输入)

分析:首先我们得知道set容器的用法,在set容器中元素不会重复并且是有序的。在set中有自带的二分函数,注意返回的是地址。那我们只需要把砍断的地方插入到set中,输入x后,再根据二分函数去查找大于x的数,再减去容器中x前面的数后,就是x所在木头的长度。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define Ios ios::sync_with_stdio(0);cin.tie();cout.tie();
#define INF 0x3f3f3f
#define mod 1000000009
using namespace std;
typedef long long ll;
int main()
{
    Ios
    set<int>s;
    ll l;ll m;
    cin>>l>>m;
    s.insert(0);s.insert(l);
    while(m--)
    {
        int x,y;cin>>x>>y;
        if(x==1)
        {
            s.insert(y);
        }else{
            auto t=s.upper_bound(y);
            cout<<*t-(*--t)<<endl;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值