ICPC 昆明 L Simone and graph coloring
这里因为memset里最开始用sizeof(d)导致t了,以后注意一下。
使用dp,O(nlogn)。具体思路就是从开始维护一个d序列,遇到一个更大的就放到d序列里,如果遇到的小于就二分查找d序列中他应该在的位置,然后替换掉即可,因为之前留的那个已经没用了。。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6+6;
int a[maxn],d[maxn],ans[maxn],n,T,len;
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
memset(d,0,n+1);
for(int i=1; i<=n; i++)scanf("%d",&a[i]);
len = 1;d[len] = a[1];ans[1]=1;
for(int i = 2; i <= n; i++) {
if(a[i] < d[len])//下降
d[++len]=a[i],ans[i]=len;
else{
int x=lower_bound(d+1,d+1+len,a[i],greater<int>())-d;//下降
d[x] = a[i],ans[i]=x;
}
}
printf("%d\n",len);
for(int i=1; i<=n; i++)printf("%d ",ans[i]);
printf("\n");
}
return 0;
}
上升序列的代码只要改一下if里的比较符,然后缺省掉lower_bound里的比较函数就可以。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5+6;
int a[maxn],d[maxn],n,T,len;
int main() {
while(scanf("%d",&n)!=EOF) {
memset(d,0,n+1);
for(int i=1; i<=n; i++)scanf("%d",&a[i]);
len = 1;d[len] = a[1];
for(int i = 2; i <= n; i++) {
if(a[i] > d[len])//上升这里>
d[++len]=a[i];
else{
int tmp=lower_bound(d+1,d+1+len,a[i])-d;//上升这里缺省
d[tmp] = a[i];
}
}
printf("%d\n",len);
}
return 0;
}