• P2652 同花顺


    P2652 同花顺

    Link

    题目背景

    所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续。

    题目描述

    现在我手里有 (n) 张扑克牌,但它们可能并不能凑成同花顺。我现在想知道,最少更换其中的多少张牌,我能让这 (n) 张牌都凑成同花顺?

    输入格式

    第一行一个整数 (n) ,表示扑克牌的张数。

    接下来 (n) 行,每行两个整数 (a_{i})(b_{i}) . 其中 (a_{i}) 表示第 (i) 张牌的花色,(b_{i}) 表示第 (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 le 10)

    • 对于 60% 的数据,(n le 10^{5})(1 le a_{i} le 10^{5})(1 le b_{i} le n)

    • 对于 100% 的数据,(n le 10^{5})(1 le a_{i}, b_{i} le 10^{9})

    前言

    这道题好ex,考试考了好几次了都没写出来(怪自己太菜了)。


    题解

    首先呢,这道题有一个比较特殊的性质,就是重复的牌一定会被我们替换掉,这就以意味着我们需要对牌进行去重。

    我们可以转化一下问题,求一下最长的符合同花顺序列的长度,这样就比较好求了。

    我们最后的答案就是 原来的牌数减去最长的符合同花顺序列的长度。

    假设,我们以这张牌作为当前同花顺序列的最后一张牌,那么前面的那几张牌的数字都是要 大于当前的牌的数字减 (n)

    所以我们可以对牌按花色排序,如果花色相同按牌的数字排序。

    我们开个队列存当前的同花顺序列,如果当前的牌 (i) 与之前的牌的花色都不同,就把整个队列清空。

    反之,枚举左端点,找到第一个与他花色不同或者数字比他小 (n) 的牌 (j),同花顺序列的长度就是 (i-j)

    可以考虑用一个队列来优化一下:

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N = 1e5+10;
    int n,cnt,ans,tot;
    queue<int> que;
    inline int read()
    {
    	int s = 0,w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s =s * 10+ch - '0'; ch = getchar();}
    	return s * w;
    }
    struct node
    {
    	int c,num;
    }q[N],a[N];
    bool comp(node a,node b)//按花色排序,花色相同按数字排序
    {
    	if(a.c == b.c) return a.num < b.num;
    	else return a.c < b.c;
    }
    int main()
    {
    //	freopen("card.in","r",stdin);
    //	freopen("card.out","w",stdout);
    	n = read();
    	for(int i = 1; i <= n; i++)
    	{
    		q[i].c = read();
    		q[i].num = read();
    	}
    	sort(q+1,q+n+1,comp);
    	for(int i = 1; i <= n; i++)//去重
    	{
    		if(q[i].c == q[i-1].c && q[i].num == q[i-1].num) continue;
    		else a[++tot] = q[i];
    	}
    	for(int i = 1; i <= tot; i++)
    	{
    		if(a[i].c != a[i-1].c)//与之前花色不同,把队列清空
    		{
    			while(!que.empty()) que.pop();
    		}
    		while(que.size() && a[que.front()].num < a[i].num - n) que.pop();//去掉数字比他小n的点
    		que.push(i);
    		ans = max(ans,(int) que.size()); //更新一下最长同花顺序列的长度
    	}
    	printf("%d
    ",n - ans);
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Scapy 工具介绍
    ubuntu虚拟机使用open-vm-tools代替vmware-tools
    docker、vmware和PD的区别
    ubuntu查看OpenGL版本
    SQL Server 常用近百条SQL语句(收藏版)
    Intellij IDEA 如何去掉 @Autowired 注入警告
    awtk-linux-fb 使用 double framebuffer 闪烁的问题
  • 原文地址:https://www.cnblogs.com/genshy/p/13662644.html
Copyright © 2020-2023  润新知