B 同花顺

题目描述
所谓同花顺,就是指一些扑克牌,它们花⾊相同,并且数字连续。
现在我手里有n 张扑克牌,但它们可能并不能凑成同花顺。我现在想知道,最
少更换其中的多少张牌,我能让这n 张牌都凑成同花顺?
输入格式
第一行一个整数n,表⽰扑克牌的张数。
接下来n 行,每行两个整数ai 和bi。其中ai 表示第i 张牌的花色,bi 表示第
i 张牌的数字。
输出格式
一行一个整数,表示最少更换多少张牌可以达到目标。
样例输入 1
5
1 1
1 2
1 3
1 4
1 5
样例输出 1
0
样例输入 2  
5
1 9
1 10
2 11
2 12
2 13
样例输出2
2
数据范围
对于30% 的数据,n ≤ 10。
对于60% 的数据,n ≤ 10^5,1 ≤ ai ≤ 10^5,1 ≤ bi ≤ n。
对于100% 的数据,n ≤ 10^5,1 ≤ ai, bi ≤ 10^9。
补充:
所谓“数字连续”,是指像这样:“4,5,6,7,8,9”。而形如“4,5,5,6,7,8,
9”(有重复数字)是不叫“连续”的。
输入数据中可能会有完全相同的牌。两张完全相同的牌是不应该出现在同一个
同花顺中的。  
分析:

题目大意
给定n张扑克牌的花色和数字,问最少替换多少张牌,可以全部凑成同花顺?
30%
爆搜即可
60%
首先我们要进行去重(相同的牌只保留一张)
取花色出现次数最多的那种牌就可以
100%
仍然是要排序去重
枚举我们同花顺在已有的牌里面的最后一张牌
寻找可能的第一张牌
不对啊,这是O(n^2)的
寻找“可能的第一张牌”的时候,有一个小技巧
令last为当前牌的最后一张牌时,“可能的第一张牌”
如果当前牌的数值是a,last这张牌的数值是b,则显然要满足a-b+1
≤n;  
如果我们的数值都是排好序的,随着我们“最后一张牌”的递增,“可能的第一张牌”显然是不降的

代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000+5;
struct card
{
    int a,b;
    bool operator <(const card& x) const {//重载小于运算符,sort函数要用到
        return a==x.a? b<x.b : a<x.a;
    }
    bool operator ==(const card& y) const {//重载等于运算符,unique函数要用到
        return (a==y.a&&b==y.b);
    }
} cd[maxn];
int n,m;
int solve(int s,int t)
{
    int i,j,ret=0;
    for(i=j=s;i<=t;++i)
    {
        while(j<t&&cd[j+1].b-cd[i].b<n) ++j;
        ret=max(ret,j-i+1);
    }
    return ret;
}
int main()
{
    freopen("card.in", "r", stdin);
    freopen("card.out", "w", stdout);
    int i,j,ans=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d%d",&cd[i].a,&cd[i].b);
    sort(cd+1,cd+n+1);
    m=unique(cd+1,cd+n+1)-cd-1;
    for(i=2,j=1;i<=m;i++)
    if(cd[i].a!=cd[i-1].a) {
        ans=max(ans,solve(j,i-1));
        j=i;
    }
    ans=max(ans,solve(j,i-1));
    printf("%d",n-ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

还有通过本题我发现了一个有趣的东西:
int i;
    for(i=1;i<=6;i++)//一个有意思的小实验,for循环语句执行时只执行到6,但i到最后变成了7;
    {}
    cout<<i<<endl;
输出7;

推断for循环语句就等于:
i=1;
    while(i<=6) i++; 
 cout<<i<<endl;
但是for循环与while语句不同的是: 
在循环语句中for循环实际执行了6次, 而while语句执行了7次。

或者是:
do
{
  i++;
 }while(i<=6);
 cout<<i<<endl
这就与for循环语句相同了。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值