zoukankan      html  css  js  c++  java
  • 题解 P4146 【序列终结者】

    题目描述

    给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作:

    将[L,R]这个区间内的所有数加上V。

    将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。

    求[L,R]这个区间中的最大值。

    最开始所有元素都是0。

    输入输出格式

    输入格式:

    第一行两个整数N,M。M为操作个数。

    以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

    输出格式:

    对于每个第3种操作,给出正确的回答。

    输入输出样例

    输入样例#1:

    4 4
    1 1 3 2
    1 2 4 -1
    2 1 3
    3 2 4
    

    输出样例#1:

    2
    

    说明

    N≤50000,M≤100000。
    

    主要思路:FHQ Treap区间操作

    算是一道模板题吧。主要是在维护区间加和区间翻转上。

    重点就是打标记。其实区间翻转的标记方式在文艺平衡树那道题里面有用到过。就是在做一个标记,标记区间是否翻转。然后在有标记的节点上交换左右子树即可。部分代码如下:

    // z[rt].col表示区间加的懒标记
    // z[rt].coll表示区间翻转的懒标记
    // z[rt].ch[0]表示rt节点的左子树
    // z[rt].ch[1]表示rt节点的右子树
    // 这个代码是下方标记的函数
    inline void push_col(int rt) {
    	if(z[rt].col) {
    		if(z[rt].ch[0]) { // 分类讨论
    			z[z[rt].ch[0]].col += z[rt].col;
    			z[z[rt].ch[0]].maxx += z[rt].col;
    			z[z[rt].ch[0]].w += z[rt].col;
    		}
    		if(z[rt].ch[1]) {
    			z[z[rt].ch[1]].col += z[rt].col;
    			z[z[rt].ch[1]].maxx += z[rt].col;
    			z[z[rt].ch[1]].w += z[rt].col;
    		}
    		z[rt].col = 0; // 最后去掉标记
    	}
    	if(z[rt].coll) { 
    		if(z[rt].ch[0]) z[z[rt].ch[0]].coll ^= 1;
    		if(z[rt].ch[1]) z[z[rt].ch[1]].coll ^= 1;
    		swap(z[rt].ch[0], z[rt].ch[1]); // 交换
    		z[rt].coll = 0; // 去标记
    	}
    }
    

    要注意的是在split和merge时加上push_col和update的操作。

    code:

    附带debug代码。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <vector>
    using namespace std;
    #define go(i, j, n, k) for(int i = j; i <= n; i += k) 
    #define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
    #define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
    #define mn 50010
    #define inf 1 << 30
    #define ll long long
    inline int read(){
        int x = 0, f = 1; char ch = getchar();
        while(ch > '9' || ch < '0') { if(ch == '-') f = -f; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return x * f;
    } 
    struct tree{
        int ch[2], pri, sze, w;
        int maxx;
        int col, coll;
    } z[mn];
    inline void update(int rt) {
        z[rt].sze = 1;
        z[rt].maxx = z[rt].w;
        if(z[rt].ch[0]) {
            z[rt].sze += z[z[rt].ch[0]].sze;
            z[rt].maxx = max(z[rt].maxx, z[z[rt].ch[0]].maxx);
        }
        if(z[rt].ch[1]) {
            z[rt].sze += z[z[rt].ch[1]].sze;
            z[rt].maxx = max(z[rt].maxx, z[z[rt].ch[1]].maxx);
        }
    }
    inline void push_col(int rt) {
        if(z[rt].col) {
            if(z[rt].ch[0]) {
                z[z[rt].ch[0]].col += z[rt].col;
                z[z[rt].ch[0]].maxx += z[rt].col;
                z[z[rt].ch[0]].w += z[rt].col;
            }
            if(z[rt].ch[1]) {
                z[z[rt].ch[1]].col += z[rt].col;
                z[z[rt].ch[1]].maxx += z[rt].col;
                z[z[rt].ch[1]].w += z[rt].col;
            }
            z[rt].col = 0;
    // 		update(rt);
        }
        if(z[rt].coll) {
            if(z[rt].ch[0]) z[z[rt].ch[0]].coll ^= 1;
            if(z[rt].ch[1]) z[z[rt].ch[1]].coll ^= 1;
            swap(z[rt].ch[0], z[rt].ch[1]);
            z[rt].coll = 0;
        }
    }
    int cnt;
    inline int newnode(int w = 0) {
        z[++cnt].maxx = w;
        z[cnt].w = w;
        z[cnt].pri = rand();
        z[cnt].sze = 1;
        z[cnt].col = z[cnt].coll = 0;
        return cnt;
    } 
    inline int merge(int x, int y) {
        if(!x || !y) return x + y;
        if(z[x].pri < z[y].pri) {
            push_col(x);
            z[x].ch[1] = merge(z[x].ch[1], y);
            update(x);
            return x;
        } else {
            push_col(y);
            z[y].ch[0] = merge(x, z[y].ch[0]);
            update(y);
            return y;
        }
    }
    inline void split(int rt, int k, int &x, int &y) {
        if(!rt) x = y = 0;
        else {
            push_col(rt);
            if(k <= z[z[rt].ch[0]].sze) {
                y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);
            } else {
                x = rt, split(z[rt].ch[1], k - z[z[rt].ch[0]].sze - 1, z[rt].ch[1], y);
            }
            update(rt);
        }
    }
    inline void debug(int rt) {
        if(!rt) return;
        if(z[rt].ch[0]) debug(z[rt].ch[0]);
        printf("%d %d %d %d
    ", z[rt].w, z[rt].maxx, z[rt].pri, z[rt].sze);
        if(z[rt].ch[1]) debug(z[rt].ch[1]);
        
    }
    int n, m, rot, xx, yy, zz;
    int main() {
        n = read(), m = read();
        go(i, 1, n, 1) {
            rot = merge(rot, newnode(0));
        }
        go(i, 1, m, 1) {
            int s = read(), l = read(), r = read(), v;
            if(s == 1) {
                v = read();
                split(rot, r, xx, zz);
                split(xx, l - 1, xx, yy);
                z[yy].col += v;
                z[yy].maxx += v;
                z[yy].w += v;
                rot = merge(merge(xx, yy), zz);
            } else if(s == 2) {
                split(rot, r, xx, zz);
                split(xx, l - 1, xx, yy);
                z[yy].coll ^= 1;
                rot = merge(merge(xx, yy), zz);
            } else if(s == 3) {
                split(rot, r, xx, zz);
                split(xx, l - 1, xx, yy);
                printf("%d
    ", z[yy].maxx);
                rot = merge(merge(xx, yy), zz);
            }
        }
    //	debug(rot);
        return 0;
    }
    
  • 相关阅读:
    英文谚语:Take that with a grain of salt
    Unity2017五子棋大战_人机_双人_UNET联网
    attenuation
    solo
    decay
    什么是PCM?它和.wav文件是什么关系?
    C++中 top()与pop()
    unity项目开发必备插件Asset Hunter 2(资源猎人2)
    unity中Camera.ScreenToWorldPoint
    自动化安装SQLSERVER和SQLSERVER补丁 转
  • 原文地址:https://www.cnblogs.com/yizimi/p/10071621.html
Copyright © 2011-2022 走看看