BZOJ1251·序列终结者
好像不能附传送门了。。这是道sb权限题。。
1251: 序列终结者
Time Limit: 20 Sec Memory Limit: 162 MBDescription
网 上有许多题,就是给定一个序列,要你支持几种操作: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
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。
【数据范围】
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 }