链接:https://ac.nowcoder.com/acm/contest/3282/G?&headNav=acm
来源:牛客网
Hasaki!lfqlfqlfq 特别喜欢玩快乐风男,并且他喜欢无缝E的感觉。
现在 lfqlfqlfq 面前有n个兵,呈线性排列编号为 1−n,每个小兵携带 ai 个金币。为了体现快乐的极致, lfqlfqlfq 知道了每个小兵携带的金币,快乐的他E往无前(也就是说他不会回头),但是快乐的他每次E的小兵的金币都严格递增,为了 lfqlfqlfq 能E到更多的小兵,请你给出他E兵的编号。如果有多个快乐方案,给出字典序最小的方案
输入描述:
第一行一个整数 n(1<=n<=1e5),表示小兵的个数。
接下来一行 n 个整数,a1,a2,…an,(1<=ai<=1e5)n,(1<=ai<=1e5)表示编号为i的小兵所携带的金币数量。
输出描述:
第一行输出一个整数 kkk,表示 lfqlfqlfq 最多能E到小兵的个数。
接下来一行输出 kkk 个整数,表示 lfqlfqlfq 能E到的小兵的下标。行末不要加空格。
说明
lfqlfqlfq 有两种E到4个小兵的方案,1 2 3 5 和 1 2 4 5,其中下标1 2 3 5的字典序小于1 2 4 5,所以答案是1 2 3 5
这个题让输出的下标的字典序最小,
https://www.cnblogs.com/xwdzuishuai/p/12081775.html
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; int n; int a[N], cnt, f[N]; int len[N], first[N]; int ans[N]; int main() { memset(f, 0x3f, sizeof(f)); scanf("%d", &n); for (int i = 1; i <= n; i ++) scanf("%d", &a[i]); for (int i = 1; i <= n; i ++) { int t = lower_bound(f + 1, f + n + 1, a[i]) - f; if(f[t] == INF) { ++ cnt; f[t] = a[i]; len[i] = t; } else { f[t] = a[i]; len[i] = t; } if(first[len[i]] == 0) first[len[i]] = i; } printf("%d\n", cnt); ans[cnt] = first[cnt]; for (int i = first[cnt] - 1; i >= 1; i --) { if(a[i] < a[ans[len[i] + 1]]) ans[len[i]] = i; } for(int i = 1; i <= cnt; i++) printf("%d%c", ans[i], i==cnt?'\n':' '); }
如果输出数的字典序最小的下标的话
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; int n; int a[N], cnt, f[N]; int len[N], first[N]; int ans[N]; int main() { memset(f, 0x3f, sizeof(f)); scanf("%d", &n); for (int i = 1; i <= n; i ++) scanf("%d", &a[i]); for (int i = 1; i <= n; i ++) { int t = lower_bound(f + 1, f + n + 1, a[i]) - f; if(f[t] == INF) { ++ cnt; f[t] = a[i]; len[i] = t; } else { f[t] = a[i]; len[i] = t; } first[len[i]] = i; } printf("%d\n", cnt); ans[cnt] = first[cnt]; for (int i = first[cnt] - 1; i >= 1; i --) { if(a[i] < a[ans[len[i] + 1]]) ans[len[i]] = i; } for(int i = 1; i <= cnt; i++) printf("%d%c", ans[i], i==cnt?'\n':' '); }