zoukankan      html  css  js  c++  java
  • 洛谷 P4146 序列终结者

    Description

    P4146 序列终结者

    Solution

    fhq-treap

    不得不说 (fhq-treap) 代码是真的短,真的好写。

    挺板子的一道题。

    • 区间加:打个 (add) 标记,不停下放即可,相应的 (maxs)(val)(add) 都要更新。

    • 区间翻转:这就是个文艺平衡树板子,不多说了。(不会的话,可以看一下我的博客 洛谷 P3391 【模板】文艺平衡树

    • 查询区间最大值:把区间对应的子树找出来,输出这个子树记录的最大值即可。

    注意 (pushup) 时要判断是否有左右子树,在向上传。

    Code

    #include <bits/stdc++.h>
    #define ls(x) t[x].ch[0]
    #define rs(x) t[x].ch[1]
    
    using namespace std;
    
    const int N = 5e4 + 10;
    int n, m, root, tot;
    struct Treap{
    	int ch[2], siz, maxs, val, wei, add, lazy;
    }t[N];
    int a, b, c;
    
    inline int read(){
    	int x = 0, f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar(); }
    	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    	return x * f;
    }
    
    inline void pushup(int x){
    	t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
    	t[x].maxs = t[x].val;
    	if(ls(x)) t[x].maxs = max(t[x].maxs, t[ls(x)].maxs);
    	if(rs(x)) t[x].maxs = max(t[x].maxs, t[rs(x)].maxs);
    }
    
    inline void pushdown(int x){
    	if(!x) return;
    	if(t[x].lazy){
    		if(ls(x)) t[ls(x)].lazy ^= 1;
    		if(rs(x)) t[rs(x)].lazy ^= 1;
    		swap(ls(x), rs(x));
    		t[x].lazy = 0;
    	}
    	if(t[x].add){
    		if(ls(x)) t[ls(x)].val += t[x].add, t[ls(x)].add += t[x].add, t[ls(x)].maxs += t[x].add;
    		if(rs(x)) t[rs(x)].val += t[x].add, t[rs(x)].add += t[x].add, t[rs(x)].maxs += t[x].add;
    		t[x].add = 0;
    	}
    }
    
    inline void split(int x, int k, int &a, int &b){
    	if(!x){
    		a = b = 0;
    		return;
    	}
    	pushdown(x);
    	if(k >= t[ls(x)].siz + 1){
    		a = x;
    		split(rs(x), k - t[ls(x)].siz - 1, rs(x), b);
    	}else{
    		b = x;
    		split(ls(x), k, a, ls(x));
    	}
    	pushup(x);
    }
    
    inline int merge(int x, int y){
    	if(!x || !y) return x | y;
    	if(t[x].wei <= t[y].wei){
    		pushdown(x);
    		rs(x) = merge(rs(x), y);
    		pushup(x);
    		return x;
    	}else{
    		pushdown(y);
    		ls(y) = merge(x, ls(y));
    		pushup(y);
    		return y;
    	}
    }
    
    inline int newnode(int k){
    	t[++tot].val = t[tot].maxs = k, t[tot].siz = 1, t[tot].wei = rand();
    	return tot;
    }
    
    inline void insert(int k){
    	root = merge(root, newnode(k));
    }
    
    inline void Add(int l, int r, int k){
    	int len = r - l + 1;
    	split(root, l - 1, a, b);
    	split(b, len, b, c);
    	t[b].maxs += k;
    	t[b].val += k;
    	t[b].add += k;
    	root = merge(merge(a, b), c);
    }
    
    inline void Reverse(int l, int r){
    	split(root, l - 1, a, b);
    	split(b, r - l + 1, b, c);
    	t[b].lazy ^= 1;
    	root = merge(merge(a, b), c);
    }
    
    inline int Query(int l, int r){
    	split(root, l - 1, a, b);
    	split(b, r - l + 1, b, c);
    	int ans = t[b].maxs;
    	root = merge(merge(a, b), c);
    	return ans;
    }
    
    int main(){
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++)
    		insert(0);
    	while(m--){
    		int op = read(), l = read(), r = read(), k;
    		if(op == 1) k = read(), Add(l, r, k);
    		else if(op == 2) Reverse(l, r);
    		else printf("%d
    ", Query(l, r));
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15157574.html

  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/xixike/p/15157574.html
Copyright © 2011-2022 走看看