CF AIM Tech Round 4 C. Sorting by Subsequences
题目链接:http://codeforces.com/contest/844/problem/C
题目大意:给出一个长度为n的序列a[n],问如果将其分为K个子序列,要求每个子序列排序之后整个序列也是有序的,那么最大的K是多少。
解题思路:首先我们考虑当前序列中和排序后的序列中对应位置相同的元素,那么显然,为了K最大,我们使每个单独成一个子序列;
现在考虑不同的元素,对于如下序列(下标--排序后--原序列):
1 2 3 4 5 6
2 6 7 9 12 13
9 13 2 7 12 6
我们知道1 4 3;2 6(下标)号元素排序后与整个序列排序后相同,简单思考一下会发现实际上对于1号元素,我们只要找9对应的排序后的序列的元素下标4,然后判断其是否为2,如果不为2,继续找7对应的下标,直到其为2,那么这个序列排序后与整个序列排序后一定是一样的。
代码:
1 const int maxn = 1e5 + 5; 2 int n; 3 int a[maxn], as[maxn]; 4 queue<int> qs[maxn]; 5 int tot; 6 bool vis[maxn]; 7 8 void solve(){ 9 tot = 0; 10 memset(vis, 0, sizeof(vis)); 11 for(int i = 0; i < n; i++) as[i] = a[i]; 12 sort(as, as + n); 13 for(int i = 0; i < n; i++){ 14 if(as[i] == a[i]){ 15 vis[i] = 1; 16 qs[tot].push(i); 17 tot++; 18 } 19 } 20 queue<int> tmq; 21 for(int i = 0; i < n; i++){ 22 if(vis[i]) continue; 23 int tma = as[i], j = lower_bound(as, as + n, a[i]) - as; 24 tmq.push(i); 25 tmq.push(j); 26 vis[j] = 1; 27 while(a[j] != tma){ 28 j = lower_bound(as, as + n, a[j]) - as; 29 tmq.push(j); 30 vis[j] = 1; 31 } 32 qs[tot++] = tmq; 33 while(!tmq.empty()) tmq.pop(); 34 } 35 printf("%d\n", tot); 36 for(int i = 0; i < tot; i++){ 37 printf("%d", qs[i].size()); 38 while(!qs[i].empty()){ 39 printf(" %d", qs[i].front() + 1); 40 qs[i].pop(); 41 } 42 puts(""); 43 } 44 } 45 int main(){ 46 scanf("%d", &n); 47 for(int i = 0; i < n; i++) scanf("%d", &a[i]); 48 solve(); 49 }
题目: