• 两个栈维护队列,两个队列维护栈小结


    两个栈维护队列

    直接上例题!!!

    jzoj 2292. 【佛山市选2010】PPMM

    一题多解,又是好题啊~~~
    首先,这题空间卡得恨死,所以线段树什么的都死了。。。
    然后呢竟然还有好多种解法,我偏偏要撞进线段树里。。。

    (solution1) 用两个栈来维护队列

    首先这是没有可减性的(就是不支持删除其中的任一元素)
    一个向右,一个向左。
    向右的支持插入,向左的支持删除。
    对于每个栈都维护一个前缀(max)(min),这样答案可以立即得到。
    然后的话如果删除的删完了,那就把插入的那个栈全部倒放到删除的这个栈中,顺便求(max)(min)
    取反操作很容易弄。

    (code)

    #include <cstdio>
    #include <algorithm>
    #define N 2000010
    #define ll long long
    #define mem(x, a) memset(x, a, sizeof x)
    #define mpy(x, y) memcpy(x, y, sizeof y)
    #define fo(x, a, b) for (register int x = (a); x <= (b); x++)
    #define fd(x, a, b) for (register int x = (a); x >= (b); x--)
    #define go(x) for (int p = tail[x], v; p; p = e[p].fr)
    using namespace std;
    int Q, z[N], z1[N], top = 0, top1 = 0;
    int val[N][2], val1[N][2];
    bool ops = 0;
    char s[7];
    
    inline int read()
    {
    	int x = 0, f = 0; char c = getchar();
    	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return f ? -x : x;
    }
    
    int main()
    {
    	freopen("pm.in", "r", stdin);
    	freopen("pm.out", "w", stdout);
    	Q = read();
    	val[0][0] = val1[0][0] = -2147483647;
    	val[0][1] = val1[0][1] = 2147483647;
    	while (Q--)
    	{
    		scanf("%s", s + 1);
    		if (s[1] == 'P')
    		{
    			if (s[2] == 'U')
    			{
    				z[++top] = read();
    				if (ops) z[top] = -z[top];
    				val[top][0] = max(val[top - 1][0], z[top]);
    				val[top][1] = min(val[top - 1][1], z[top]);
    			}
    			else
    			{
    				if (! top && ! top1) continue;
    				if (top1) {top1--; continue;}
    				while (top)
    				{
    					z1[++top1] = z[top--];
    					val1[top1][0] = max(val1[top1 - 1][0], z1[top1]);
    					val1[top1][1] = min(val1[top1 - 1][1], z1[top1]);
    				}
    				top1--;
    			}
    		} 
    		else
    		{
    			if (s[2] == 'I') ops = ! ops;
    			else
    			{
    				if (! top && ! top1) continue;
    				if (ops == 0) printf("%d
    ", max(val[top][0], val1[top1][0]));
    				else printf("%d
    ", -min(val[top][1], val1[top1][1]));
    			}
    		}
    	}
    	return 0;
    }
    

    (solution2) 单调队列

    我们可以用单调队列来维护。
    也就是两个单调队列,一个维护(min),一个维护(max)存的是原队列中的位置!
    然后呢我们插入的话直接按照单调队列插入即可。
    删除呢就看看单调队列的最左边(如果不是被覆盖了就一定是(l)),然后看看是否需要删除。
    剩下两个操作都很容易了。

    (DYDL's) (code)

    #include <cstdio>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <iostream>
    // #include <ctime>
    // #include <cmath>
    // #include <map>
    // #include <vector>
    // #include <set>
    // #include <string>
    #define open_in(x) freopen(#x".in", "r", stdin)
    #define open_out(x) freopen(#x".out", "w", stdout)
    #define open_(x) freopen(#x".in", "w", stdout)
    #define open(x) open_in(x); open_out(x)
    #define mes(x, y) memset(x, y, sizeof(x))
    #define mec(x, y) memcpy(x, y, sizeof(x))
    #define fo(x, y, z) for (int (x) = (y); (x) <= (z); (x)++)
    #define fd(x, y, z) for (int (x) = (y); (x) >= (z); (x)--)
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef unsigned long long ull;
    const int N = 2000010;
    const int M = 1e9 + 7;
    // inline int Random(int a, int b) {return rand() % (b - a + 1) + a;}
    template<class T>
    inline T read(T &x) {
    	int f = 1; char ch = getchar(); x = 0;
    	while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    	return x *= f;
    }
    
    int n, a[N], l, r, flag;
    char c1, c2;
    struct Queue {
    	int arr[N], l, r;
    	Queue() {l = 1, r = 0;}
    	inline bool Empty() {return l > r;}
    	inline int Back() {return arr[r];}
    	inline int Front() {return arr[l];}
    	inline void Push(int x) {arr[++r] = x;}
    	inline void PopBack() {r--;}
    	inline void PopFront() {l++;}
    } Qmin, Qmax;
    int main() {
    //	open_in(PPMM);
    	l = 1, r = 0; flag = 0;
    	read(n);
    	while (n--) {
    		c1 = getchar(); c2 = getchar();
    		if (c1 == 'P') {
    			if (c2 == 'U') {
    				/* PUSH */
    				int x; read(x);
    				if (flag) x = -x;
    				a[++r] = x;
    				while (!Qmin.Empty() && a[Qmin.Back()] >= x) Qmin.PopBack();
    				Qmin.Push(r);
    				while (!Qmax.Empty() && a[Qmax.Back()] <= x) Qmax.PopBack();
    				Qmax.Push(r);
    			} else {
    				/* POP */
    				scanf("P
    ");
    				if (l <= r) {
    					if (Qmin.Front() == l) Qmin.PopFront();
    					if (Qmax.Front() == l) Qmax.PopFront();
    					l++;
    				}
    			}
    		} else {
    			if (c2 == 'A') {
    				/* MAX */
    				scanf("X
    ");
    				if (l <= r) {
    					printf("%d
    ", (flag ? -a[Qmin.Front()] : a[Qmax.Front()]));
    				}
    			} else {
    				/* MINUS */
    				scanf("NUS
    ");
    				flag ^= 1;
    			}
    		}
    	}
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    C#中任意类型数据转成JSON格式
    数据库用户映射到SQL Server登录名
    浅述WinForm多线程编程与Control.Invoke的应用
    Git错误一例
    提高VS2010/VS2012编译速度
    给有兴趣、有责任要讲课、分享的朋友推荐两本书
    中国剩余定理
    中国剩余定理
    洛谷1546 最短网路
    洛谷1111 修复公路
  • 原文地址:https://www.cnblogs.com/jz929/p/12268678.html
Copyright © 2020-2023  润新知