其他分享
首页 > 其他分享> > 练习赛40

练习赛40

作者:互联网

Begin:
2019-03-25 18:35

PDD:250rlb

A

HihoCoder-1728 卡片游戏

(45)

卡片游戏

思路

用一个set来存储还没被集合包括的数,然后O(N)跑一遍循环,
模拟翻每张牌,然后更新答案ans=min(ans,*s.begin())

B

(55)

HihoCoder-1729 宝藏坐标

宝藏坐标

思路

先枚举逗号放的位置,在枚举左半部分小数点的位置,如果可行的话,
再去枚举右半部分的小数点位置,如果也可行,计入答案,然后按照字
典序排序答案。注意可能不含小数点的情况,本题细节较多。

C

(70)

HihoCoder-1722 最小差值

最小差值

思路

一道超好好好的yy题,主要思路是尺取。
首先看题目, 1≤ N × M ≤ 200000 ,这暗示了我们得用一维数组储存,
所以我们开个结构体a{x,id},其中x记录该点的值,id记录该点所属数组编号。
然后我们按x打小sort一遍,那么对于这n*m个点,假设l,r为最小/最大值的数组
下标,那么对于[l,r]中的结构体来说,只要它们的id包含了 1~n 所有的数组
那么这两个值就是可取的。那么就好了a。

代码

#include<bits/stdc++.h>
using namespace std;
#define min(a,b) a<b?a:b
int n,m,ans=1000000+9;
struct node{
    int x,id;
}a[200005];
bool cmp(node a,node b){return a.x<b.x;}
int tot;
map<int,int>cnt;
inline int read(){
    int x=0; char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        for(int j=1,d;j<=m;j++)d=read(),a[++tot]=(node){d,i};
    sort(a+1,a+tot+1,cmp);
    int l=1,r=0;
    for(;l<=tot;l++){
        while(r<=tot&&cnt.size()<n){
            r++;
            cnt[a[r].id]++;
        }
        if(r<=tot)ans=min(ans,a[r].x-a[l].x);
        cnt[a[l].id]--;
        if(!cnt[a[l].id])cnt.erase(a[l].id);
    }
    printf("%d",ans);
}

D

(80)

HihoCoder-1483 区间价值

区间价值

思路

又一道yy题,首先二分[0,n*(n+1)/2]范围内的数,即枚举可能的第k小值,然后check部分,用尺取思路。

实现

step1

由于数据范围较大,我们先离散化数据,注意此题相同的数离散后对应值应相同

struct node{
    int d,id;
}a[N];
bool cmp(node x,node y){return x.d<y.d;}
for(int i=1;i<=n;i++)scanf("%lld",&a[i].d),a[i].id=i;
        sort(a+1,a+n+1,cmp);
        tmp=0;
        for(int i=1;i<=n;i++){
            if(a[i].d!=a[i-1].d)tmp++;
            b[a[i].id]=tmp;
        }

step2

二分答案,注意要long long

long long l=0,r=1ll*n*(n+1)/2,ans;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid))r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld\n",ans);

step3

check部分的函数

bool check(long long p){
    for(int i=0;i<=tmp;i++)cnt[i]=0;//注意计数用的cnt不要用map,不然会TLE
    long long now=0,res=0;
    //now:当前区间[l,r]的区间值,res:目前为止区间值小于p的区间个数
    for(int i=1,l=1;i<=n;i++){
        now+=cnt[b[i]];
        cnt[b[i]]++;//统计相同对数
        while(l<=i&&now>p){
            //由于要选择区间值小于p的区间
            cnt[b[l]]--;
            now-=cnt[b[l]];
            l++;
        }
        res+=i-l+1;
        //[l,r],[l+1,r],[l+2,r]...[r-1,r],[r,r]共r-l+1个区间的区间值都是<p的
    }
    return res>=k;
}

代码

标签:练习赛,int,HihoCoder,mid,long,40,ans,id
来源: https://www.cnblogs.com/Tieechal/p/11189356.html