Description
给你一个长度为N的序列{ai}和M个操作
1.查询第k个数的值
2.将第k个数增加d
3.查询一段区间的和
4.查询一段区间的最大值
5.将一段区间镜面翻转(例如序列{1,2,3,4,5,6},将从2到5的区间翻转后得到序列{1,5,4,3,2,6})
对于除操作2,5以外的操作,输出相应的答案
Input
第一行两个正整数N,M
第二行N个整数,为初始的序列
第三行到底M+2行,每行若干个整数
·如果第一个数为1,那么后面一个正整数k,表示查询第k个数的值
·如果第一个数是2,那么后面两个正整数k,d,表示将ak增加d
·如果第一个数为3,那么后面两个正整数l,r,表示查询从al到ar的区间和
·如果第一个数为4,那么后面两个正整数l,r,表示查询从al到ar的最大值
·如果第一个数为5,那么后面两个正整数l,r,表示翻转从al到ar的这个区间
Output
除操作2,5外每个操作输出占一行,一个整数,为本次提问的答案
Sample Input
6 8
1 2 3 4 5 6
1 4
3 2 5
4 2 2
5 2 5
3 1 3
5 2 5
2 5 1
4 1 6
Sample Output
4
14
2
10
6
Hint
2<=N<=100000
1<=M<=100000
原序列1<=ai<=1000
每次1<=k<=N,1<=l<=r<=N,1<=d<=1000
【分析】
好吧这是一道模版题。
注意当前当前节点打标记时,状态要为已更新。
【代码】
//Ciocio's code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <utility>
#include <functional>
#include <vector>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define INF (~0U>>3)
#define sf scanf
#define pf printf
#define MAXN 100010
struct SplayNode{
#define node SplayNode
node* ch[2];
node* fa;
int sz;
int val;
int max;
int sum;
bool lazy;
node(){
ch[0]=ch[1]=fa=NULL;
sz=val=max=sum=lazy=0;
}
}*null=new node(),*root;
node Pool[MAXN];
node* New=Pool;
int N,M;
int A[MAXN];
void Read(int& x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}
void Updata(node* r){
r->sz=r->ch[0]->sz+r->ch[1]->sz+1;
r->max=r->sum=r->val;
if(r->ch[0]!=null){
r->max=max(r->max,r->ch[0]->max);
r->sum+=r->ch[0]->sum;
}
if(r->ch[1]!=null){
r->max=max(r->max,r->ch[1]->max);
r->sum+=r->ch[1]->sum;
}
}
void Putdown(node* r){
node* lc=r->ch[0];
node* rc=r->ch[1];
lc->lazy=!lc->lazy;
rc->lazy=!rc->lazy;
swap(lc->ch[0],lc->ch[1]);
swap(rc->ch[0],rc->ch[1]);
r->lazy=false;
}
void Rotate(node* r,bool k){
node* t=r->fa;
t->ch[!k]=r->ch[k];
r->ch[k]->fa=t;
r->fa=t->fa;
if(t==t->fa->ch[0]) t->fa->ch[0]=r;
else t->fa->ch[1]=r;
r->ch[k]=t;
t->fa=r;
Updata(t);
Updata(r);
if(root==t) root=r;
}
node* Get(int val,node* fa){
New->ch[0]=New->ch[1]=null;
New->fa=fa;
New->val=New->max=New->sum=val;
New->sz=1;
New->lazy=false;
return New++;
}
#define Mid ((Left+Right)>>1)
node* Build(node* f,int Left,int Right){
if(Right<Left) return null;
if(Left==Right){
node* p=Get(A[Left],f);
return p;
}
node* p=Get(A[Mid],f);
p->ch[0]=Build(p,Left,Mid-1);
p->ch[1]=Build(p,Mid+1,Right);
Updata(p);
return p;
}
void Splay(node* r,node* f){
while(r->fa!=f){
if(r->fa->fa==f){
if(r==r->fa->ch[0]) Rotate(r,1);
else Rotate(r,0);
}
else{
node* a=r->fa;
node* b=a->fa;
if(a==b->ch[0]){
if(r==a->ch[0])
Rotate(a,1),Rotate(r,1);
else
Rotate(r,0),Rotate(r,1);
}
else{
if(r==a->ch[1])
Rotate(a,0),Rotate(r,0);
else
Rotate(r,1),Rotate(r,0);
}
}
}
}
node* Ask(node* r,int k){
if(r->lazy) Putdown(r);
if(k==r->ch[0]->sz+1) return r;
if(k<=r->ch[0]->sz)
return Ask(r->ch[0],k);
else
return Ask(r->ch[1],k-r->ch[0]->sz-1);
}
void Init(){
Read(N);Read(M);
rep(i,2,N+1) Read(A[i]);
N+=2;
A[1]=A[N]=INF;
root=Build(null,1,N);
}
void Solve(){
int T,k,d,l,r;
while(M--){
Read(T);
if(T==1){
Read(k);
pf("%d\n",Ask(root,k+1)->val);
}
else if(T==2){
Read(k);
Read(d);
Splay(Ask(root,k+1),null);
root->val+=d;
Updata(root);
}
else{
Read(l);
Read(r);
l++;r++;
Splay(Ask(root,l-1),null);
Splay(Ask(root,r+1),root);
if(T==3){
pf("%d\n",root->ch[1]->ch[0]->sum);
}
else if(T==4){
pf("%d\n",root->ch[1]->ch[0]->max);
}
else{
node* p=root->ch[1]->ch[0];
p->lazy=!p->lazy;
swap(p->ch[0],p->ch[1]);
}
}
}
}
int main(){
Init();
Solve();
return 0;
}