luogu P2652 同花顺解题报告

题目描述

所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续。
现在我手里有 n 张扑克牌,但它们可能并不能凑成同花顺。我现在想知道,最
少更换其中的多少张牌,我能让这 n 张牌凑成一个同花顺?

输入格式

第一行一个整数 n,表示扑克牌的张数。
接下来 n 行,每行两个整数 a i 和 b i 。其中 a i 表示第 i 张牌的花色,b i 表示第
i 张牌的数字。
(注意:这里的牌上的数字不像真实的扑克牌一样是 1 到 13,具体见数据范围)

输出格式

一行一个整数,表示最少更换多少张牌可以达到目标。

样例输入 1

5
11
12
13
14
15

样例输出 1

0

样例输入 2

5
19
1 10
2 11
2 12
2 13

样例输出 2

2

数据范围

对于 30% 的数据,n ≤ 10。
对于 60% 的数据,n ≤ 10^5 ,1 ≤ a i ≤ 10^5 ,1 ≤ b i ≤ n。
对于 100% 的数据,n ≤ 10^5 ,1 ≤ a i , b i ≤ 10^9 。

题解

介于题目中没有给出是否可能会有重复的牌 先想办法把重复的牌刷掉 顺便离散化
所以最先做的就是排序 关键字1为花色 关键字2为大小
我们要求的应该是整个序列的同色最大上升子序列
枚举 关键是注意枚举过程中花色的变化 以及 该子序列的最后一个数与第一个数的差距位置不能多于n

代码

#include <cstdio>
#include <algorithm>
#define ll long long
#define R register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    while (c>'9'||c<'0') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
const int maxn=1e5+5;
int n;
struct node{int col,num;}e[maxn],t[maxn];
int tt,ans,cnt;
bool cmp(node x,node y) {return x.col==y.col?(x.num<y.num):(x.col<y.col);}
void init(){
    n=read();
    for (R int i(1);i<=n;++i) e[i].col=read(),e[i].num=read();
    sort(e+1,e+1+n,cmp);
    for (R int i(1);i<=n;++i){//离散化
        if (e[i].col==e[i-1].col&&e[i].num==e[i-1].num) continue;
        t[++cnt]=e[i];
    }
}
void doit(){
    for (R int i(1);i<=cnt;++i){
        tt=0;
        for (R int j(i);j>=1;--j){
            if (t[j].col==t[i].col&&t[i].num-t[j].num+1<=n) ++tt;//1.花色相同 2.差距位置小于等于n
            else break;
        }
        ans=max(ans,tt);
    }
    printf("%d\n",n-ans);
}
signed main(){
//  file("card");
    init();
    doit();
    return 0;
}

转载于:https://www.cnblogs.com/cancers/p/11303801.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值