网上有许多题,就是给定一个序列,要你支持几种操作: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。
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
对于每个第3种操作,给出正确的回答。
4 4 1 1 3 2 1 2 4 -1 2 1 33 2 4
2
#include <bits/stdc++.h> //#include <ext/pb_ds/tree_policy.hpp> //#include <ext/pb_ds/assoc_container.hpp> //using namespace __gnu_pbds; using namespace std; #define pi acos(-1) #define endl '\n' #define me(x) memset(x,0,sizeof(x)); #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++) #define close() ios::sync_with_stdio(0); typedef long long LL; const int INF=0x3f3f3f3f; const LL LINF=0x3f3f3f3f3f3f3f3fLL; const int dx[]={-1,0,1,0,-1,-1,1,1}; const int dy[]={0,1,0,-1,1,-1,1,-1}; const int maxn=1e3+5; const int maxx=1e5+100; const double EPS=1e-7; const int MOD=1000000007; #define mod(x) ((x)%MOD); template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);} template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);} template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));} template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));} //typedef tree<pt,null_type,less< pt >,rb_tree_tag,tree_order_statistics_node_update> rbtree; /*lch[root] = build(L1,p-1,L2+1,L2+cnt); rch[root] = build(p+1,R1,L2+cnt+1,R2);中前*/ /*lch[root] = build(L1,p-1,L2,L2+cnt-1); rch[root] = build(p+1,R1,L2+cnt,R2-1);中后*/ long long gcd(long long a , long long b){if(b==0) return a;a%=b;return gcd(b,a);} struct Splay_Tree { struct node { int val,Max,add,Size,son[2];//add =lazy val为节点的值 Max节点最大值 //Size 节点大小,son为儿子 bool rev;//节点是否翻转 void init(int _val) { val=Max=_val; Size=1; add=rev=son[0]=son[1]=0; } }T[maxx]; int fa[maxx],root;//fa是节点的父亲,root是根 void pushUp(int x)//从下往上更新 { T[x].Max=T[x].val,T[x].Size=1; if(T[x].son[0]) { T[x].Max=max(T[x].Max,T[T[x].son[0]].Max); T[x].Size+=T[T[x].son[0]].Size; } if(T[x].son[1]) { T[x].Max=max(T[x].Max,T[T[x].son[1]].Max); T[x].Size+=T[T[x].son[1]].Size; } } void pushDown(int x) { if(x==0) return ; if(T[x].add)//如果有lazy的话 { if(T[x].son[0])//左儿子更新 { T[T[x].son[0]].val+=T[x].add; T[T[x].son[0]].Max+=T[x].add; T[T[x].son[0]].add+=T[x].add; } if(T[x].son[1])//右儿子更新 { T[T[x].son[1]].val+=T[x].add; T[T[x].son[1]].Max+=T[x].add; T[T[x].son[1]].add+=T[x].add; } T[x].add=0; } if(T[x].rev) { if(T[x].son[0]) T[T[x].son[0]].rev^=1; if(T[x].son[1]) T[T[x].son[1]].rev^=1; swap(T[x].son[0],T[x].son[1]); T[x].rev=0; } } void Rotate(int x,int kind) { int y=fa[x],z=fa[y]; T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;//B T[x].son[kind]=y,fa[y]=x;//y T[z].son[T[z].son[1]==y]=x,fa[x]=z;//z pushUp(y); }//kind 为1是 !kind==0 T[y]的左儿子变成了T[x]的右儿子 //zig zag的合并 void Splay(int x,int goal) { if(x==goal) return ;//goal 是根 while(fa[x]!=goal)//父亲不是根的话 { int y=fa[x],z=fa[y]; pushDown(z),pushDown(y),pushDown(x); int rx=T[y].son[0]==x,ry=T[z].son[0]==y;//rx==1 左儿子 //rx==0 右儿子 if(z==goal) Rotate(x,rx);//旋转一次 else //旋转两次 { if(rx==ry) Rotate(y,ry); else Rotate(x,rx); Rotate(x,ry); } } pushUp(x); if(goal==0) root=x; } int Select(int pos) { int u=root; pushDown(u); while(T[T[u].son[0]].Size!=pos) { if(pos<T[T[u].son[0]].Size) u=T[u].son[0];//如果小于显然在左儿子上 else { pos-=T[T[u].son[0]].Size+1; u=T[u].son[1]; } pushDown(u); } return u; } void update(int L,int R,int val) { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); T[T[v].son[0]].Max+=val; T[T[v].son[0]].val+=val; T[T[v].son[0]].add+=val; } void Reverse(int L,int R) { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); T[T[v].son[0]].rev^=1;//打标记 } int query(int L,int R) { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); return T[T[v].son[0]].Max; } int build(int L,int R) { if(L>R) return 0; if(L==R) return L; int mid=(L+R)>>1,sL,sR; T[mid].son[0]=sL=build(L,mid-1);//同线段树 T[mid].son[1]=sR=build(mid+1,R); fa[sL]=fa[sR]=mid; pushUp(mid); return mid; } void init(int n) { T[0].init(-INF),T[1].init(-INF),T[n+2].init(-INF);//三个元素 for(int i=2;i<=n+1;i++) T[i].init(0); root=build(1,n+2),fa[root]=0; fa[0]=0,T[0].son[1]=root,T[0].Size=0; } }; Splay_Tree hehe; int main() { int n,m; cin>>n>>m; hehe.init(n); for(int i=0,a,b,c,d;i<m;i++) { cin>>a; if(a==1) { cin>>b>>c>>d; hehe.update(b,c,d); } else if(a==2) { cin>>b>>c; hehe.Reverse(b,c); } else { cin>>b>>c; printf("%d\n",hehe.query(b,c)); } } }