题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215
题意:给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]<=a[i+1]。我们每次对当前数组删除非排序过的串,合并剩下的串,继续删,直到排序完成。
解法:双向链表模拟过程,设置一个队列,用于存可能产生非排序过的串的头结点,每次从队列中拿出一个头结点判断后面的情况,若还能继续删除,则将头结点的上一个结点放入队列继续判,知道没有别的结点为止。
#include <bits/stdc++.h> using namespace std; const int maxn = 100010; int a[maxn], Next[maxn], Last[maxn]; int que[maxn], top; int main() { int T, n; scanf("%d", &T); while(T--){ scanf("%d", &n); a[0] = 0; Next[0] = 1; Last[n+1] = n; int ans = n; for(int i=1; i<=n; i++){ Next[i] = i+1; Last[i] = i-1; scanf("%d", &a[i]); que[top++] = i; } int flag = 1; while(flag) { flag = 0; int s = 0; int now = 0; while(now < top){ int item = que[now]; int len = 0; while(Next[item]<=n){ if(a[item] > a[Next[item]]){ len++; flag = 1; item = Next[item]; } else break; } if(len) ans = ans - len - 1; if(len){ Next[Last[que[now]]] = Next[item]; Last[Next[item]] = Last[que[now]]; que[s++] = Last[que[now]]; } while(now < top && que[now] <= item) now++; } top = s; } printf("%d ", ans); int now = 0; while(now <= n){ if(now != 0) printf("%d ", a[now]); now = Next[now]; } printf(" "); } return 0; }