【bzoj1251】序列终结者 Splay
2015-12-08 21:59
337 查看
Description
网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。Input
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。Output
对于每个第3种操作,给出正确的回答。Sample Input
[code]4 4 1 1 3 2 1 2 4 -1 2 1 3 3 2 4
Sample Output
[code]2
【数据范围】
N<=50000,M<=100000。
HINT
Source
Splay加了点操作,多存点东西就可以了……pushdown多写点,函数大同小异…
代码:
[code]#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int SZ = 1000010; const int INF = 1000000010; struct node{ node *ch[2],*f; int sz,cnt,v,maxn,add; bool flag; void maintain() { sz = ch[0] -> sz + ch[1] -> sz + cnt; maxn = max(v,max(ch[0] -> maxn,ch[1] -> maxn)); } void setc(node *x,int d) { (ch[d] = x) -> f = this; } void pushdown(); int dir() { return f -> ch[1] == this; } }T[SZ], *root, *null; int Tcnt = 0; node* newnode(int x,node *fa) { node *k = T + (Tcnt ++); k -> ch[1] = k -> ch[0] = null; k -> cnt = k -> sz = 1; k -> v = k -> maxn = x; k -> f = fa; k -> add = k -> flag = 0; return k; } void node::pushdown() { if(flag) { flag = 0; if(ch[0] != null) ch[0] -> flag ^= 1; if(ch[1] != null) ch[1] -> flag ^= 1; swap(ch[0],ch[1]); } if(add) { if(ch[0] != null) ch[0] -> add += add,ch[0] -> maxn += add,ch[0] -> v += add; if(ch[1] != null) ch[1] -> add += add,ch[1] -> maxn += add,ch[1] -> v += add; add = 0; } } void rotate(node *p) { p -> f -> pushdown(); p -> pushdown(); node *fa = p -> f; int d = p -> dir(); fa -> f -> setc(p,fa -> dir()); fa -> setc(p -> ch[d ^ 1],d); fa -> maintain(); p -> setc(fa,d ^ 1); p -> maintain(); if(fa == root) root = p; } void splay(node *p,node *rt = null) { while(p -> f != rt) { p -> pushdown(); if(p -> f -> f == rt) rotate(p); else { if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p); else rotate(p),rotate(p); } } } node* find(node *p,int k) { while(p != null) { p -> pushdown(); int l = p -> ch[0] -> sz + 1; int r = p -> ch[0] -> sz + p -> cnt; if(l <= k && k <= r) return p; if(k > r) k -= r,p = p -> ch[1]; else p = p -> ch[0]; } } void change(node *p,int l,int r,int d) { l ++; r ++; node *pre = find(root,l - 1); node *suf = find(root,r + 1); splay(pre); splay(suf,root); root -> ch[1] -> ch[0] -> add += d; root -> ch[1] -> ch[0] -> maxn += d; root -> ch[1] -> ch[0] -> v += d; } void reverse(node *p,int l,int r) { l ++; r ++; node *pre = find(root,l - 1); node *suf = find(root,r + 1); splay(pre); splay(suf,root); root -> ch[1] -> ch[0] -> flag ^= 1; } int ask_max(node *p,int l,int r) { l ++; r ++; node *pre = find(root,l - 1); node *suf = find(root,r + 1); splay(pre); splay(suf,root); return root -> ch[1] -> ch[0] -> maxn; } int n,m; void build(node* &p,int l,int r,node *fa) { if(l > r) return ; int mid = (l + r) >> 1; p = newnode(0,fa); build(p -> ch[0],l,mid - 1,p); build(p -> ch[1],mid + 1,r,p); p -> maintain(); } void init() { null = newnode(-INF,null); null -> sz = null -> cnt = 0; root = null; root = newnode(-INF,null); root -> ch[1] = newnode(INF,root); build(root -> ch[1] -> ch[0],1,n,root -> ch[1]); root -> ch[1] -> maintain(); root -> maintain(); } int main() { scanf("%d%d",&n,&m); init(); while(m --) { int k; scanf("%d",&k); int l,r,v; if(k == 1) { scanf("%d%d%d",&l,&r,&v); change(root,l,r,v); } else if(k == 2) { scanf("%d%d",&l,&r); reverse(root,l,r); } else { scanf("%d%d",&l,&r); printf("%d\n",ask_max(root,l,r)); } } return 0; }
相关文章推荐
- 学习总结(15-12-8)
- js验证IP及子网掩码的合法性
- angularJs中的隐藏和显示
- 小明A+B
- 简单的进度条
- [Objective-C] - NSObject
- jquery学习(一)-选择器
- 小猪的数据结构辅助教程——2.1 线性表中的顺序表
- ios 页面之间的传值:属性传值,代理传值,block传值
- 控制器与导航控制器及之间的相互跳转
- unity导入模型的transform.position和外框renderer.center不一样
- 基于webdriver的IE设置
- 经典排序SQL
- atitit.标准时间格式 相互转换 秒数 最佳实践
- Windows 2003扩充磁盘空间
- 在opencv3中进行图片人脸检测
- time函数
- js判断ip地址,子网掩码,网关的逻辑性检查
- jobs
- 数据库简单查询