2017 ACM/ICPC Asia Regional Qingdao Online Brute Force Sorting

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215

题目大意:给出一个序列,一种操作: 对于当前数列中所有满足a[ i ]>a [  i+1 ]  ( i<n)的i,同时删去所有的a[i]和a[i+1]。

操作执行到无法执行时停止,求最终的序列。

这题有个显然的性质:每个元素最多被删除一次。

利用这个性质,如果建立一个队列,队列内存所有a [ x ] - a[ pre[x] ]<0的 x和pre[x] 值,然后把这些x,pre[x]标记为即将被删去,一起删去,然后利用链表结构来维护删除后现存的前后关系,再把新产生的a [ x ] - a[ pre[x] ]<0的 x和pre[x] 值加入队列, 一直重复操作直到队列为空时停止。

因为加入队列的值一定会被删去,而一个值最多被重复删去2次,所以时间复杂度是O(n)的。

代码:

#include <bits/stdc++.h>

using namespace std;
inline void read(int &x){
    char ch;
    bool flag=false;
    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
}

inline void read(long long &x){
    char ch;
    bool flag=false;
    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
}

const int MAXN = 120000;
struct zy{
int st,ed;
    zy( int st,int ed):st(st),ed(ed){}
    zy(){}
};

vector< zy > Q;
int n;
int a[ MAXN ];
bool vis[ MAXN ];
bool use[ MAXN ];
int pre[ MAXN ];
int nex[ MAXN ];
int ans[ MAXN ];
vector< pair<int , int > > T;


void Delete(int x){
int a=pre[x];
int b=nex[x];
pre[ b ]= a;
nex[ a ]= b;
}

void doit(){
read(n);
for (int i=1;i<=n;i++)
    read(a[i]);
memset( vis , 0 ,sizeof( vis ));
vis[0]=1; vis[n+1]=1;
for (int i=1;i<=n;i++)
{
    pre[i]=i-1;
    nex[i]=i+1;
}

Q.clear();
for (int i=2;i<=n;i++)
    if ( a[i]-a[i-1] <0 )
        Q.push_back( zy( i-1 ,i ) );

while ( !Q.empty() )
{
    while ( !Q.empty() )
    {
        zy tmp;
        tmp = Q.back();
        Q.pop_back();
        int x2=tmp.st;
        int x3=tmp.ed;
        T.push_back( make_pair(x2,x3 ) );
    }
    if (T.empty() )
        break;
    for (auto S:T)
        {
            int x=S.first;
            int y=S.second;
            if (!vis[x])
                Delete(x);
            if (!vis[y])
                Delete(y);
            vis[ x ] = 1; vis[ y ] = 1;
        }
    for (auto S:T)
        {
            int x=S.first;
            int y=S.second;
            int t1=pre[x];
            int t2=nex[t1];
            if ( ( ( !vis[ t1 ] ) && ( !vis[ t2 ] ) ) && ( a[t2]-a[t1]<0) )
                Q.push_back( zy ( t1 , t2  ) );
        }
    T.clear();
}
int cnt=0;
for (int i=1;i<=n;i++)
    if ( vis[ i ]==0)
        ans[++cnt]=a[i];
printf("%d\n",cnt);
for (int i=1;i<=cnt;i++)
    printf("%d ",ans[i]);
puts("");
}

int main(){
    int T;
    read(T);
    for (int i=1;i<=T;i++)
        doit();
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u012602144/article/details/78021034