HDU 6215 Brute Force Sorting (链表维护数组)

来源:互联网 发布:东华医疗软件 编辑:程序博客网 时间:2024/05/16 16:20


Brute Force Sorting

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 709    Accepted Submission(s): 176


Problem Description
Beerus needs to sort an array of N integers. Algorithms are not Beerus's strength. Destruction is what he excels. He can destroy all unsorted numbers in the array simultaneously. A number A[i] of the array is sorted if it satisfies the following requirements.
1. A[i] is the first element of the array, or it is no smaller than the left one A[i1].
2. A[i] is the last element of the array, or it is no bigger than the right one A[i+1].
In [1,4,5,2,3], for instance, the element 5 and the element 2 would be destoryed by Beerus. The array would become [1,4,3]. If the new array were still unsorted, Beerus would do it again.
Help Beerus predict the final array.
 

Input
The first line of input contains an integer T (1T10) which is the total number of test cases.
For each test case, the first line provides the size of the inital array which would be positive and no bigger than 100000.
The second line describes the array with N positive integers A[1],A[2],,A[N] where each integer A[i] satisfies 1A[i]100000.
 

Output
For eact test case output two lines.
The first line contains an integer M which is the size of the final array.
The second line contains M integers describing the final array.
If the final array is empty, M should be 0 and the second line should be an empty line.
 

Sample Input
551 2 3 4 555 4 3 2 151 2 3 2 151 3 5 4 252 4 1 3 5
 

Sample Output
51 2 3 4 5 021 2 21 3 32 3 5
 

Source
2017 ACM/ICPC Asia Regional Qingdao Online
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6216 6215 6214 6213 6212 

题意:


给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]<=a[i+1]。我们每次对当前数组删除非排序过的串,合并剩下的串,继续删,直到排序完成。


思路:


我们可以采用数组模拟一个双向链表,再用一个队列来模拟整个的删除过程.队列中存放的是可能从该点开始产生非排序序列的下标,每次从队列中拿出一个结点,看后面的是否满足排序,不满足就删除这一段然后一直后移,直到整个队列为空.

这里需要注意要将删除结点的上一个结点加入继续判断

总结: 之前总结的这类区间变动问题 一般用并茶几pre数组维护, 现在又学到了 双端链表。。当然是数组模拟的, 链表存的是下标

比赛里用pre数组维护的, 感觉很对 就是wa,自己测得阳历都对, 暴力对拍才发现错了。。是因为用pre数组维护,没有链表的更新,使其依然是一条链,用pre相当于只跑了一遍。。

 suf[pre[que[cur]]] = suf[p];
 pre[suf[p]] = pre[que[cur]];
 que[cnt++] = pre[que[cur]];


#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;const int maxn = 1e5 + 7;int que[maxn], a[maxn], pre[maxn], suf[maxn], n, top;int main(){    int _;    cin >> _;    while(_--)    {        top = 0;        scanf("%d", &n);        for(int i = 1; i <= n; i++)        {            pre[i] = i-1;            suf[i] = i+1;            scanf("%d", &a[i]);            que[top++] = i;        }        suf[0] = 1;        int ans = n, flag = 0;        while(1)  //一轮一轮的删, 如果没有改动过,说明都是有序的了        {            int cnt = 0, cur = 0, flag = 0;            while(cur < top)  //当前这一轮            {                int p = que[cur], num = 0;                while(suf[p] <= n && a[p] > a[suf[p]])  //把一个连续的删掉                {                    flag = 1;                    num++;                    p = suf[p];                }                if(num)                {                    ans -= num+1;                    suf[pre[que[cur]]] = suf[p];  //维护链表,使其联通                    pre[suf[p]] = pre[que[cur]];                    que[cnt++] = pre[que[cur]];                }                while(que[cur] <= p && cur < top)  //修改当前指针                    cur++;            }            top = cnt;            if(!flag) break;  //没有就跳出        }        printf("%d\n", ans);        int cur = 0;        while(cur <= n)        {            if(cur)                printf("%d ",a[cur]);            cur = suf[cur];        }        puts("");    }    return 0;}