zoukankan      html  css  js  c++  java
  • 【uoj#174】新年的破栈 贪心

    题目描述

    给你一个长度为 $n$ 的序列和一个空的双端队列,每次进行3种操作种的一种:

    1.将序列中编号最小的数加入到双端队列的队尾;
    2.从双端队列的队尾取出一个数;
    3.从双端队列的队头取出一个数。

    不断进行操作直至无法进行为止。

    要求最后依次取出的数构成的序列的字典序最小。求这个字典序最小的序列。

    $nle 10^5$ ,保证序列中的数互不相同。


    题解

    贪心

    题目描述这么多,其实是一道水题 = =

    由于要求字典序最小,因此每次贪心使得当前位置的数尽可能小。

    那么考虑下一次弹队列的数的位置,只有三种可能:队头、队尾、序列中。

    因此取出 队头的数、队尾的数、序列中的最小数 ,以最小的一个作为答案。如果在队列里则直接弹出;否则将序列中的数不断加到队列中直至加到最小数,然后弹出。

    时间复杂度为排序的 $O(nlog n)$

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    using namespace std;
    int a[N] , mp[N] , q[N];
    int main()
    {
    	int T;
    	scanf("%d" , &T);
    	while(T -- )
    	{
    		int n , i , j , p = 1 , l = 1 , r = 0 , x , y , z;
    		scanf("%d" , &n);
    		for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
    		a[n + 1] = 1 << 30 , mp[n + 1] = n + 1;
    		for(i = n ; i ; i -- )
    		{
    			if(a[i] < a[mp[i + 1]]) mp[i] = i;
    			else mp[i] = mp[i + 1];
    		}
    		for(i = 1 ; i <= n ; i ++ )
    		{
    			x = a[mp[p]];
    			if(l <= r) y = a[q[r]] , z = a[q[l]];
    			else y = z = 1 << 30;
    			if(x < y && x < z)
    			{
    				for(j = p ; j <= mp[p] ; j ++ ) q[++r] = j;
    				printf("%d " , a[q[r -- ]]) , p = j;
    			}
    			else if(y < x && y < z) printf("%d " , a[q[r -- ]]);
    			else printf("%d " , a[q[l ++ ]]);
    		}
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    hiveserver2 with kerberos authentication
    python Basic usage
    python Quicksort demo
    Python HeapSort
    mrunit for wordcount demo
    CCDH证书
    Hadoop question list
    Hadoop Yarn core concepts
    Hadoop Resource
    Hadoop could not find or load main class
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8300939.html
Copyright © 2011-2022 走看看