2017ICPC青岛网络赛 Brute Force Sorting

Brute Force Sorting

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


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
  
  
5 5 1 2 3 4 5 5 5 4 3 2 1 5 1 2 3 2 1 5 1 3 5 4 2 5 2 4 1 3 5
 

Sample Output
  
  
5 1 2 3 4 5 0 2 1 2 2 1 3 3 2 3 5
 

题解:

这是一道模拟题,限定每次找到序列中所有的单调下降的连续的子串,然后删除掉,不断重复上述步骤,最后使得序列单调非降。

这里有一个重要的结论,就是说我在第一步去掉了[L,R]这个区间,那么在第二次的时候,只有a[L-1]和a[R+1]这两个数字有可能形成单调下降的子串(长度最大为2)。

举例说明:

序列:4 6 2 3 3 5 2 2 3

下标:1 2 3 4 5 6 7 8 9

这是初始序列,在第一步找单调下降的连续的子串的时候我们找到了两个区间

[2,3]和[6,7]

然后我们删除掉两个区间

变成了

序列:4 3 3 2 3

下标:1 4 5 8 9

然后我们接下来只需要考虑下b标为(1、4)和下标为(5、8)的元素

然后我们发现a[1] = 4 > a[4] = 3所以删除掉a[1]和a[4]       发现a[5] > a[8],所以删除掉a[5]和a[8]

之后序列变成

序列:3

下标:9

到这里就完成了。

所以这个题目的思路就是这的:

1.找出单调下降区间,放入vector1里面

2.把vector2清空。把vector1里面的区间依次拿出来,如果两个区间完全相邻或者重叠,则将他们合并成一个大区间,放入vector2里面去。

3.把vector1清空。对vector2里面的区间[L,R]依次拿出来,如果L > 1 && R < n && a[L-1] > a[R - 1],那么就L--,R++;然后把这个区间再次放入vector1里面去。

4.如果区间有变化,那么就转到第2步,否则执行第5步。

5.所有vector1里面的区间都是被删掉的,然后取补集就是答案。

代码:

#include <bits/stdc++.h>
using namespace std;
int T,n;
const int maxn = 1e5+7;
typedef pair<int,int> P;
int a[maxn];
vector<P> vec[2];
int mark[maxn];
void init(){
    memset(mark,0,sizeof(mark));
}
int main(){
    scanf("%d",&T);
    int cnt = 0;
    while(T--){
    	vec[0].clear();
    	vec[1].clear();
        init();
        scanf("%d",&n);
        for(int i = 0;i < n;i++){
            scanf("%d",&a[i]);
        }
        int last = 0;
        int len = 0;
        int kk = 0;
        for(int i = 1;i < n;i++){
            if(a[i] < a[i-1]){
                len++;
            }
            else{
                if(len){
                    vec[0].push_back(make_pair(last,i-1));
                    kk++;
                }
                len = 0;
                last = i;
            }
        }
        if(len){
            vec[0].push_back(make_pair(last,n-1));
            kk++;
        }
        if(!kk){
            printf("%d\n",n);
            for(int i =0 ;i < n;i++){
                printf("%d ",a[i]);
            }
            puts("");
            continue;
        }
        int flag = 1;
        while(flag){
            flag = 0;
            vec[1].clear();
            P pre = vec[0][0];
            for(int i = 1;i < vec[0].size();i++){
                P now = vec[0][i];
                if(pre.second + 1 >= now.first){
                    pre.second = now.second;
                } 
                else{
                    vec[1].push_back(pre);
                    pre = now;
                }
            }
            vec[1].push_back(pre);
            vec[0].clear();
            for(int i = 0;i < vec[1].size();i++){
                P pp = vec[1][i];
                if(pp.first > 0 && pp.second < n-1){
                    if(a[pp.first-1] > a[pp.second+1]){
                        flag = 1;
                        pp.first --;
                        pp.second ++;
                    }
                }
                vec[0].push_back(pp);
            }
        }
        for(int i = 0;i < vec[1].size();++i){
            P p = vec[1][i];
            for(int i = p.first;i <= p.second;++i){
                mark[i] = 1; 
            }
        }
        vector<int> ans;
        for(int i = 0;i < n;i++){
            if(!mark[i]){
                ans.push_back(a[i]);
            }
        }
        printf("%d\n",ans.size());
        for(int i = 0;i < ans.size();++i){
            printf("%d ",ans[i]);
        }
        puts("");
    }
    return 0;
}
/*
1 
7
4 4 4 3 3 3 2

1
5
1 2 3 2 1

*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值