您的位置:首页 > 其它

hdu 5773 The All-purpose Zero 思维转化+nlogn LIS

2016-07-30 01:43 309 查看

hdu 5773 The All-purpose Zero 思维转化+nlogn LIS

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5773
题意:给定一个长度为N的序列S,(0 < n <= 100000,0<= S[i] <= 1000000),0可以变成任意数字(包括负数),求最长上升子序列长度。
分析:0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的。因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量。为了保证严格递增,我们可以将每个权值S[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的。 
能想出这样的思路,真值得好好膜拜一下。

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;

//#pragma comment(linker, "/STACK:1024000000,1024000000")

#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
#define fst             first
#define snd             second
#define lson			l, mid, rt << 1
#define rson			mid + 1, r, rt << 1 | 1

const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int MAXN = 100000 + 5;

int N, M, T;
int S[MAXN], A[MAXN], B[MAXN];

int LIS() {
int len = 0;
for (int i = 1; i <= M; i++) {
int pos = lower_bound(B, B + len, A[i]) - B;
if (len == pos) {
B[len++] = A[i];
} else {
B[pos] = A[i];
}
}
return len;
}

int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
scanf("%d", &T);
int cas = 0;
while (T --) {
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
scanf("%d", &S[i]);
}
int SUM = 0;
M = 0;
for (int i = 1; i <= N; i++) {
if (S[i] == 0) SUM ++;
else A[++M] = S[i] - SUM;
}
int len = LIS();
printf("Case #%d: %d\n", ++cas, len + SUM);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: