同花顺

洛谷P2652 同花顺

这是在2017日照夏令营的D1T2,我认为质量相当高的一道题,第一次在赛场上做的时候爆零了,当时态度不很端正,暴力不想打,想投机取巧骗分,还是不要把希望压在不确定的事情上,有多少分实实在在拿着就拿着,然后能力之外的再尽可能获得更多。言归正传,这个用类似枚举的思路来做,枚举一个同花顺的左右端点,具体是外循环先确定j,然后枚举可能的第一个左端点,然后用n-maxans);这个的证明是向李子晗学习的,回来后我又在洛谷上做了一遍,50分。接下来是核心部分:先说我为什么是错的,我的ij中间是连续的递增+1的同花顺,然后这一部分不用换,n-最大的连续序列就是答案,但正解是a[右端点].num-a[左端点].num+1<=n;

证明如下:

j                                                                         i

 |                 |       |           |                                   |

这是i和j确定的序列,满足上面那个条件j就左移,为什么呢?因为要保证i,j内的序列是连续递增的(在换完之后),现在只要证明它能换完就可以了,如果a[右端点].num-a[左端点].num+1<=n

,那就是说序列总长度最多为n,好了,现在我们有n个数,那怎么换都能换到+1 递增上去,空缺就都能补上,ij之间的都不用动,所以求最大的ij之外的数的个数就好了。

注:今天向苗若桐学习了结构体重载运算符,会用了unique函数。

 

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int color;
    int num;
    bool operator < (const node &a)const
    {
        if(color==a.color)
        return num<a.num;
        return color<a.color;
    }
    
    bool operator == (const node &a)const
    {
        return num==a.num&&color==a.color;
    }
    
    bool operator != (const node &a)const
    {
        return !(*this==a);
    }
    
}a[100001];


int n;
int ans;


void Cin(int &x)
{
    char c=getchar();x=0;
    while(c>'9'||c<'0') c=getchar();
    while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
}

int main()
{

    cin>>n;
    int i;
    for(i=1;i<=n;i++)  Cin(a[i].color),Cin(a[i].num);
    sort(a+1,a+n+1);
    int from=1,to=1;
    int l=unique(a+1,a+n+1)-a;
    int maxn=0;
    for(i=1;i<l;i++)
    {
      for(int j=i;i>=1;j--)
      {
          if(a[i].color==a[j].color&&a[i].num-a[j].num+1<=n)
          maxn++;
          else
          break;
      }
      ans=max(ans,maxn);
      maxn=0;
    }
    cout<<n-ans;
    return 0;
}
原文地址:https://www.cnblogs.com/war1111/p/7308714.html