每日练习6

1.

https://codeforces.com/contest/1660/problem/C

*1300 字符串贪心

删除情况必然是从左找到右的第一个相同的然后中间的删去,如果里面有里面的先删掉。

比较巧妙的解决办法,如果前面有了就直接加二然后清空Pre,往后遍历如果没有Pre我就给我的Pre置成true,最后输出r-m。

#include<bits/stdc++.h>
using namespace std;
const int N=26;
int main()
{
    int t;
    cin >> t;
    while(t--) {
        string s;
        cin >> s;
        int m=0,r=s.size();
        vector<bool> Pre(N,false);

        for(auto &i:s) {
            if(Pre[i-'a']) {
                m+=2;
                for(int i=0;i<26;i++) Pre[i]=false;
            }
            else {
                Pre[i-'a']=true;
            }
        }
        cout << r-m << endl;
    }
}

2.

*1600

https://codeforces.com/contest/1660/problem/D  

按照0划分区域用solve,然后每一个区域里面先统计我的正负值,然后左边扫一次和右边扫一次找到我的最早到达的负值,然后使用前缀和统计这左右边界的绝对值等于2的元素数量,这样就能选择哪边应该来删除,最后再用前缀和可以计算我的大小(因为abs只有0,1,2三个数字),比较大小之后最后输出。

#include <bits/stdc++.h>
using namespace std;
int maxl=0,maxr=0;
vector<int> Pre;
vector<int> A;
int n;
void solve(int l,int r) {
    if(l>r||r>n) return;
    int fu=0;
    for(int i=l;i<=r;i++) {
        if(A[i]<0) {
            fu++;
        }
    }

    if(fu&1) {
        int x=0,y=0;
        for(int i=l;i<=r;i++) {
            if(A[i]<0) {
                x=i;
                break;
            }
        }

        for(int i=r;i>=l;i--) {
            if(A[i]<0) {
                y=i;
                break;
            }
        }

        if(Pre[r]-Pre[x]>Pre[y-1]-Pre[l-1]) {
            l=x+1;
        }else {
            r=y-1;
        }
    }
    
    if(Pre[r]-Pre[l-1]>Pre[maxr]-Pre[maxl-1]) {
        maxr=r;
        maxl=l;
    }
}
int main()
{
    int t;
    cin >> t;
    while(t--) {
        cin >> n;
        A.resize(n+1,0);
        Pre.resize(n+1,0);
        for(int i=1;i<=n;i++) {
            cin >> A[i];
            Pre[i]=Pre[i-1]+(abs(A[i])>=2);
        }
        maxl=1;
        maxr=0;
        if(n==1) {
            if(A[1]>=1) {
                cout << "0 0\n";
            }else {
                cout << "1 0\n";
            }
            continue;
        }

        int last=0;
        for(int i=1;i<=n;i++) {
            if(A[i]==0) {
                solve(last+1,i-1);
                last=i;
            }
        }
        if(A[n]!=0) {
            solve(last+1,n);
        }
        cout << maxl-1 << " " << n-maxr << endl;
    }
}

3.

https://codeforces.com/problemset/problem/1786/B  

*1300的贪心

前面的都想到了,就是最后面的时候我没有考虑到向左和喷头在蛋糕中间具有的普适性。我那时候想着用分类讨论的办法,但是写了一个小时发现非常困难实现。最后面发现,如果向右边是喷头右边界到蛋糕右边界是至少,左边界是至多。但是如果向左的话右是至多,左是至少,然后这种情况带来的效果和负数抵消了,因为我abs更大的我实际值更小,所以我至多的左边界应该是最负数最小的情况,导致我仍然取min保持了我需要的答案,最后比较还是是不是l<=r.。然后在中间的情况,左边界是正的右是负的,在我右移的时候带来的效果还是我的最小值是0,然后左移的还是最大值是个整数。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while(t--) {
        int n,m,h,max_x=-0x3f3f3f3f,min_x=0x3f3f3f3f;
        cin >> n >> m >> h;
        vector<int> A(n),B(n);

        for(int i=0;i<n;i++) {
            cin >> A[i];
        }
        for(int i=0;i<n;i++) {
            cin >> B[i];

            max_x=max(max_x,B[i]+h-(A[i]+m));
            min_x=min(min_x,B[i]-h-(A[i]-m));
        }

        cout << ( (max_x<=min_x) ? "YES" : "NO" )<< endl;
    }
}

4.

*1300 

模拟算贡献,CodeForces - 1778B 。一遍过,唯一需要注意的就是最后面的变化我的+d大小的时候我既可以选择增大我的Hash[B[i]]也可以减小我的Hash[B[i-1]]。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while(t--) {
        int n,m,d;
        cin >> n >> m >> d;
        map<int,int> Hash;
        vector<int> B(m+1);
        for(int i=1;i<=n;i++) {
            int x;
            cin >> x;
            Hash[x]=i;
        }

        for(int i=1;i<=m;i++) {
            cin >> B[i];
        }

        bool flag=false;
        int min_v=0x3f3f3f3f;
        for(int i=2;i<=m;i++) {
            if(Hash[B[i]]<=Hash[B[i-1]]) {
                flag=true;
                break;
            }else {
                if(Hash[B[i]]>Hash[B[i-1]]+d) {
                    flag=true;
                    break;
                }else {
                    //step1
                    min_v=min(min_v,Hash[B[i]]-Hash[B[i-1]]);
                    //step2
                    if(d+2<=n) {
                        min_v=min(min_v,Hash[B[i-1]]+d+1-Hash[B[i]]);
                    }
                }
            }
        }
        if(flag) {
            cout << 0 << endl;
        }else {
            cout << min_v << endl;
        }
    }
}

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值