版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83215267
传送门
解析:
按照第一位 排序从大到小,求 的最少的下降序列的划分数。
转换一下,求 的最少下降序列个数。
根据 定理,由于没有相等,我们要求的就是 的最长上升子序列的长度。
对于输出方案,我们在每个上升序列的位置维护一个 ,能够补到这个位置的数就能够在最后的下降序列中出现在以 开头的序列中。并查集维护一下就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(int a){
static char ch[13];
if(a==0)return (void)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs int N=1000006;
int fa[N];
inline int getfa(int x){
while(x^fa[x])x=fa[x]=fa[fa[x]];
return x;
}
inline void merge(int u,int v){
u=getfa(u);
v=getfa(v);
fa[max(u,v)]=min(u,v);
}
int pos[N],tot;
int len;
int a[N],head[N];
int b[N];
int id[N];
int n;
signed main(){
n=getint();
for(int re i=1;i<=n;++i){
int x=getint(),
y=getint();
b[x]=y;
id[x]=i;
fa[i]=i;
}
for(int re i=n;i;--i){
int c=b[i];
if(len==0||c>a[len]){
a[++len]=c;
head[len]=id[i];
}
else{
int k=lower_bound(a+1,a+len+1,c)-a;
merge(head[k],id[i]);
a[k]=c;
}
}
cout<<len<<"\n";
for(int re i=1;i<=n;++i)if(fa[i]==i)pos[i]=++tot;
for(int re i=1;i<=n;++i)outint(pos[getfa(i)]),pc(' ');
return 0;
}