P6403 STUDENTSKO 题解
发现没人用二分 + 贪心求最长不下降子序列的做法?那作为最优解的我就来发一篇吧。
题意简述
给定
解法
-
如何转化为最长不下降子序列问题?
显然,每个数应在的组是确定的,所以可以先对整个序列
得到
-
如何用二分 + 贪心求最长不下降子序列?
维护一个单调栈
-
时间复杂度
AC 代码(76ms)
#include<bits/stdc++.h>
#define ll long long
#define gch getchar()
#define ub upper_bound
using namespace std;
ll rd()
{
ll f=1,x=0; char c;
while (!isdigit(c=gch)) if (c==45) f=-1;
while (isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=gch;
return f*x;
}
void wt(ll x)
{
if (x<0) putchar('-'),x=-x;
if (x>9) wt(x/10);
putchar(x%10+'0');
}
const int N=5e3+5;
int n,k,t,c,b[N],s[N];
struct node
{
int v,p;
bool operator<(const node &x){return v<x.v;}
}a[N];
void in() //读入
{
n=rd(),k=rd();
for(int i=1;i<=n;i++)a[i].v=rd(),a[i].p=i;
}
void pre() //预处理
{
sort(a+1,a+n+1); //排序
for(int i=1;i<=n;i++)b[a[i].p]=(i-1)/k+1; //分组
}
void slv() //求最长不下降子序列
{
s[++c]=b[1];
for(int i=2;i<=n;i++)
{
if(b[i]>=s[c])s[++c]=b[i]; //满足单调性就直接入栈
else t=ub(s+1,s+c+1,b[i])-s,s[t]=b[i]; //否则,用二分+贪心
}
}
int main()
{
in();pre();slv();wt(n-c); //答案是n-c
return 0;
}