BZOJ1251·序列终结者

好像不能附传送门了。。这是道sb权限题。。

1251: 序列终结者

Time Limit: 20 Sec  Memory Limit: 162 MB

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

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

Sample Output

2
【数据范围】
N<=50000,M<=100000。

很简单的splay,维护区间最大值,翻转信息。

学习了链式建树,但是后来实验发现nlogn建树和链式建树效率基本相同(链式建树后面需要反转的次数较多)

HINT:T[0].Max = -2147483647,这点很重要。。如果某点没有前驱,那么更新最大值的时候。。→_→

Codes:

  1 #include <set>
  2 #include <queue>
  3 #include <cmath>
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <iostream>
  8 #include <algorithm>
  9 using namespace std;
 10 const int N = 50010;
 11 #define fa(i) T[i].p
 12 #define L(i) T[i].s[0]
 13 #define R(i) T[i].s[1]
 14 #define Loc(i) (T[fa(i)].s[1]==i)
 15 #define Sets(a,b,c) {T[a].s[c] = b; fa(b) = a;}
 16 #define For(i,n) for(int i=1;i<=n;i++)
 17 #define Rep(i,l,r) for(int i=l;i<=r;i++)
 18
 19 struct tnode{
 20     int s[2],size,p,markp,markr,Max,v;
 21 }T[N];
 22
 23 int n,m,root = 1,tot;
 24 int l,r,op,delta;
 25
 26 void Pushdown(int i){
 27     if(T[i].markp){
 28         if(L(i))  {T[L(i)].markp+=T[i].markp;T[L(i)].Max  +=T[i].markp;T[L(i)].v+=T[i].markp;}
 29         if(R(i))  {T[R(i)].Max  +=T[i].markp;T[R(i)].markp+=T[i].markp;T[R(i)].v+=T[i].markp;}
 30         T[i].markp = 0;
 31     }
 32     if(T[i].markr){
 33         if(L(i)) T[L(i)].markr ^= 1;
 34         if(R(i)) T[R(i)].markr ^= 1;
 35         swap(L(i),R(i));
 36         T[i].markr = 0;
 37     }
 38 }
 39
 40 void Rot(int x){
 41     int y = fa(x) , z = fa(y);
 42     int lx = Loc(x) , ly = Loc(y);
 43     Pushdown(y);Pushdown(x);
 44     Sets(y,T[x].s[lx^1],lx);
 45     Sets(z,x,ly);
 46     Sets(x,y,lx^1);
 47     T[y].size = T[L(y)].size + T[R(y)].size + 1;
 48     T[y].Max  = max(max(T[L(y)].Max,T[R(y)].Max),T[y].v);
 49 }
 50
 51 void Splay(int i,int goal){
 52     while(fa(i)!=goal){
 53         if(fa(fa(i))!=goal) Rot(fa(i));
 54         Rot(i);
 55     }
 56     if(!goal) root = i;
 57     T[i].size = T[L(i)].size + T[R(i)].size + 1;
 58     T[i].Max  = max(max(T[L(i)].Max,T[R(i)].Max),T[i].v);
 59 }
 60
 61 inline int Rank(int i,int rank){
 62     Pushdown(i);
 63     if(T[L(i)].size + 1 == rank)   return i;
 64     else  if(T[L(i)].size >= rank) return Rank(L(i),rank);
 65     else                           return Rank(R(i),rank-T[L(i)].size - 1);
 66 }
 67
 68 /*inline void Build(){//链式建树
 69     For(i,n+2) {
 70         T[i].p=i-1;
 71         T[i].s[1]=i+1;
 72         T[i].size=n+3-i;
 73         T[i].v=T[i].s[0]=T[i].markr=T[i].markp=T[i].Max=0;
 74     }
 75     T[n+2].s[1]=0;
 76     T[0].Max=-2147483647;
 77 }*/
 78
 79 inline void Build(int l,int r,int &i,int p){
 80     if(l>r) return;
 81     int m = (l+r)>>1;
 82     i=++tot;
 83     T[i].p = p; T[i].size = 1;T[i].markp = T[i].markr = T[i].v = T[i].Max = 0;
 84     Build(l,m-1,L(i),i);Build(m+1,r,R(i),i);
 85     T[i].size = T[L(i)].size + T[R(i)].size + 1;
 86 }
 87
 88 inline void Reserve(int l,int r){
 89     Splay(Rank(root,l),0);
 90     Splay(Rank(root,r+2),root);
 91     T[L(R(root))].markr ^= 1;
 92 }
 93
 94 inline void Plus(int l,int r,int delta){
 95     Splay(Rank(root,l),0);
 96     Splay(Rank(root,r+2),root);
 97     T[L(R(root))].markp+=delta;
 98     T[L(R(root))].Max += delta;
 99     T[L(R(root))].v+=delta;
100 }
101
102 inline void Query(int l,int r){
103     Splay(Rank(root,l),0);
104     Splay(Rank(root,r+2),root);
105     printf("%d\n",T[L(R(root))].Max);
106 }
107
108 int main(){
109     scanf("%d%d",&n,&m);
110     Build(0,n+1,root,0);T[0].Max = -2147483647;
111    // Build();
112     For(i,m){
113         scanf("%d",&op);
114         if(op==1) {
115             scanf("%d%d%d",&l,&r,&delta);
116             Plus(l,r,delta);
117         }
118         else{
119             scanf("%d%d",&l,&r);
120             if(op==2) Reserve(l,r);
121             else      Query(l,r);
122         }
123     }
124     return 0;
125 }

BZOJ1251·序列终结者

时间: 2024-09-30 18:32:22

BZOJ1251·序列终结者的相关文章

[BZOJ1251]序列终结者

试题描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量--这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个"库"可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. [问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V. 2.

bzoj1251: 序列终结者 (splay)

splay可以用于维护序列,比如noi的维修序列,比如这道 发现当时splay没写总结,也没题解 然后重新写splay竟然耗了一个晚上 结果是因为max[0]没有附最小值!!血一样的教训 最后祭出inline大法才过,我的splay真的慢到吐血 {$inline on} {$M 1000000000,0,maxlongint} const //mm=maxlongint>>2; maxn=60000; var size,left,right,mark,fa,value,max:array[0.

【bzoj1251】序列终结者 splay

序列终结者 Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. [问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

【BZOJ】1251: 序列终结者(splay)

http://www.lydsy.com/JudgeOnline/problem.php?id=1251 不行..为什么写个splay老是犯逗,这次又是null的mx没有赋值-maxlongint... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #inc

BZOJ 1251: 序列终结者( splay )

先orz一下clj...我的splay跟着他写的... 这道题很普通的splay我调了这么久 T T , 就是因为 null 的值初始化为0 , 结果就挂了... -------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

bzoj 1251: 序列终结者 2011-12-20

1251: 序列终结者Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 650  Solved: 277[Submit][Status][Discuss]Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可

【CodeVS4665】序列终结者

Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V. 2. 将[L,R

伸展树复习 (bzoj 1251 序列终结者)

本来要看LCT的,确发现自己弱得连splay都忘记了,复习一发,顺便重写一发 关键点: 1. 伸展树为左小右大的二叉树,所以旋转操作不会影响树的性质 2. 区间操作为: int u = select(L - 1), v = select(R + 1); splay(u, 0); splay(v, u); //通过旋转操作把询问的区间聚集到根的右子树的左子树下 因为伸展树为左小右大的二叉树,旋转操作后的所以对于闭区间[L, R]之间的所有元素都聚集在根的右子树的左子树下 因为闭区间[L, R],