2019牛客暑期多校训练营(第三场)

A Graph Games

B Crazy Binary String

题意:传送门
题解:从都是 0 0 0 1 1 1组成的序列中截取一个子串,一个子序列,使得截取出来的 0 0 0 1 1 1的个数相同,子序列就很好办,直接取序列中 0 0 0 1 1 1个数最小的一个就可以,对于子串而言,可以考虑成这样的,将序列中的 0 0 0处理成 − 1 -1 1,将序列中的 1 1 1处理成 1 1 1,进行前缀和,也就是说如果存在一个子串的话,那么必然这个子串相加和为 0 0 0,然后记录前缀和出现的最左边的值和最右边的值即可。
附上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+5;
int n,a[N],cnt0,cnt1,dp[N],minn[2*N],maxx[2*N],res;
int main()
{
    scanf("%d",&n);
    memset(minn,0x3f,sizeof(minn));
    memset(maxx,-1,sizeof(maxx));
    minn[N-3]=0;
    maxx[N-3]=0;
    for(int i=1,tmp;i<=n;i++){
        scanf("%1d",&tmp);
        if(tmp==0){
            cnt0++;
            a[i]=-1;
        }else if(tmp==1){
            cnt1++;
            a[i]=1;
        }
        dp[i]=dp[i-1]+a[i];
        tmp=dp[i]+1e5+2;
        minn[tmp]=min(minn[tmp],i);
        maxx[tmp]=max(maxx[tmp],i);
        res=max(maxx[tmp]-minn[tmp],res);
    }
    printf("%d %d\n",res,2*min(cnt0,cnt1));
    return 0;
}

C Guessing ETT

D Big Integer

E Trees in the Pocket II

F Planting Trees

题意:传送门
题解:给的pdf说的相当好了,直接粘过来了。
在这里插入图片描述
附上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+5;
int n,a[N],cnt0,cnt1,dp[N],minn[2*N],maxx[2*N],res;
int main()
{
    scanf("%d",&n);
    memset(minn,0x3f,sizeof(minn));
    memset(maxx,-1,sizeof(maxx));
    minn[N-3]=0;
    maxx[N-3]=0;
    for(int i=1,tmp;i<=n;i++){
        scanf("%1d",&tmp);
        if(tmp==0){
            cnt0++;
            a[i]=-1;
        }else if(tmp==1){
            cnt1++;
            a[i]=1;
        }
        dp[i]=dp[i-1]+a[i];
        tmp=dp[i]+1e5+2;
        minn[tmp]=min(minn[tmp],i);
        maxx[tmp]=max(maxx[tmp],i);
        res=max(maxx[tmp]-minn[tmp],res);
    }
    printf("%d %d\n",res,2*min(cnt0,cnt1));
    return 0;
}

G Removing Stones

H Magic Line

题意:传送门
题解:画一条线将所有点分成两半,两关键字排序,先按照x排,再按照y排,直接看中间两个点,如果x不相同,就可以通过画竖线稍微偏一点来确定,如果x相同的情况下,那么就得画一条横轴偏斜的线将两个拆开,正好将这条线穿过中间两个点的y轴中间即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
struct node{
    int x,y;
    bool operator < (const node p){
        if(x==p.x) return y>p.y;
        return x<p.x;
    }
}a[maxn];
int main(){
  
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].x,&a[i].y);
        }
        sort(a+1,a+n+1);
        int cnt=n/2;
        int x1,x2,y1,y2;
        if(a[cnt].x==a[cnt+1].x){
            x1=a[cnt].x-1;
            x2=x1+2;
            y1=-1e8;
            y2=a[cnt+1].y-y1+a[cnt+1].y+1;
        }else{
            x1=a[cnt].x;
            y1=-1e8;
            x2=x1+1;
            y2=1e9-1;
        }
        printf("%d %d %d %d\n",x1,y1,x2,y2);
    }
}

I Median

J LRU management

题意:传送门
题解:直接使用unorder_map与list模拟即可。

#include<bits/stdc++.h>
#define ll long long
#define pli pair<ll,int>
#define iter list<pli>::iterator
using namespace std;
int T,q,m,opt,v;
char s[15];
ll trans()
{
    ll ans=1;
    for(int i=0;s[i];i++){
        ans=ans*10+s[i]-'0';
    }
    return ans;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        unordered_map<ll,iter>mp;
        list<pli>lis;
        scanf("%d%d",&q,&m);
        for(int i=0;i<q;i++){
            scanf("%d%s%d",&opt,s,&v);
            ll tmp=trans();
            if(opt==0){
                if(mp.find(tmp)==mp.end()){
                    printf("%d\n",v);
                    lis.push_back({tmp,v});
                    mp[tmp]=--lis.end();
                }else{
                    v=(*mp[tmp]).second;
                    printf("%d\n",v);
                    lis.erase(mp[tmp]);
                    lis.push_back({tmp,v});
                    mp[tmp]=--lis.end();
                }
                if((int)lis.size()>m){
                    mp.erase(lis.front().first);
                    lis.pop_front();
                }
            }else{
                if(mp.find(tmp)==mp.end()){
                    printf("Invalid\n");
                }else{
                    iter pos=mp[tmp];
                    if(v==0)printf("%d\n",(*pos).second);
                    else if(v==1){
                        if(pos==--lis.end()){
                            printf("Invalid\n");
                        }else{
                            printf("%d\n",(*++pos).second);
                        }
                    }else{
                        if(pos==lis.begin()){
                            printf("Invalid\n");
                        }else{
                            printf("%d\n",(*--pos).second);
                        }
                    }
                }
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值