一道複雜的二叉平衡樹,因爲有區間操作,所以用splay寫,注意細節。
算是模板題吧
翻轉操作並不是將他暴力翻轉,只是開一個bool變量標記。
(debug函數請忽略。。。。。。。)
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define ull unsigned long long
#define ll long long
#define inf 200009
#define INF 2147483647
using namespace std;
struct Splay{
int val;//值
int siz,son[2],fa;//兒子大小 兒子節點 父節點
int maxsub,maxl,maxr,sumv;//最大子序列維護 左兒子最大序列 右兒子最大序列 和維護 (類似線段樹)
int p,set;//翻轉標記 makesame操作標記
}t[inf];
int arr[inf];
int len,root;
queue <int> q;//循環使用被del的數組空間,防止mle
void debug(){
printf("\nDEBUG\n");
for (int i=0;i<=len;i++){
printf("%d: fa=%d son[0]=%d son[1]=%d l=%d r=%d max=%d sum=%d p=%d set=%d\n",i,t[i].fa,t[i].son[0],t[i].son[1],t[i].maxl,t[i].maxr,t[i].maxsub,t[i].sumv,t[i].p,t[i].set);
}
}
void pushup(int u){//類似線段樹的pushup、pushdown
if (!u){
return;
}
t[u].maxl=max(t[t[u].son[0]].maxl,t[t[u].son[0]].sumv+t[u].val+max(0,t[t[u].son[1]].maxl));
t[u].maxr=max(t[t[u].son[1]].maxr,t[t[u].son[1]].sumv+t[u].val+max(0,t[t[u].son[0]].maxr));
t[u].maxsub=max(t[u].val+max(0,t[t[u].son[0]].maxr)+max(0,t[t[u].son[1]].maxl),max(t[t[u].son[0]].maxsub,t[t[u].son[1]].maxsub));
//最大子序列維護公式
t[u].sumv=t[t[u].son[0]].sumv+t[t[u].son[1]].sumv+t[u].val;
t[u].siz=t[t[u].son[0]].siz+t[t[u].son[1]].siz+1;
return;
}
void pushdown(int u){
if (!u){
return;
}
if (t[u].p){
int revu=t[u].son[0];
if (revu){
swap(t[revu].son[0],t[revu].son[1]);
swap(t[revu].maxl,t[revu].maxr);
t[revu].p^=1;
}
revu=t[u].son[1];
if (revu){
swap(t[revu].son[0],t[revu].son[1]);
swap(t[revu].maxl,t[revu].maxr);
t[revu].p^=1;
}
t[u].p=0;
}
if (t[u].set!=-INF){
int covu=t[u].son[0];
if (covu){
t[covu].set=t[covu].val=t[u].set;
t[covu].sumv=t[covu].set*t[covu].siz;
t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(t[covu].set,t[covu].sumv);
}
covu=t[u].son[1];
if (covu){
t[covu].set=t[covu].val=t[u].set;
t[covu].sumv=t[covu].set*t[covu].siz;
t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(t[covu].set,t[covu].sumv);
}
t[u].set=-INF;
}
return;
}
void rotate(int u,int p){//splay的旋轉,具體操作請看博客
int v=t[u].fa;
t[v].son[!p]=t[u].son[p];
t[t[v].son[!p]].fa=v;
t[u].son[p]=v;
t[u].fa=t[v].fa;
t[t[v].fa].son[t[t[v].fa].son[1]==v]=u;
t[v].fa=u;
pushup(v);
pushup(u);
return;
}
void splay(int u,int to){
while(t[u].fa!=to){
// debug();
if (t[t[u].fa].fa==to){
rotate(u,t[t[u].fa].son[0]==u);
}
else{
int f=t[u].fa,grandf=t[f].fa;
int p=(t[grandf].son[0]==f);
if (t[f].son[p]==u){
rotate(u,!p);
rotate(u,p);
}
else{
rotate(f,p);
rotate(u,p);
}
}
pushup(u);
// debug();
}
if (to==0){
root=u;
}
return;
}
int newtree(int v){// 循環使用被del的數組空間,防止mle
int u;
if (q.empty()){
len++;
u=len;
}
else{
u=q.front();
q.pop();
}
t[u].val=v;
t[u].maxl=t[u].maxr=t[u].maxsub=-INF;
t[u].p=0;
t[u].set=-INF;
return u;
}
int build(int l,int r){//建樹
if (l>r){
return 0;
}
int mid=(l+r)/2,lson=0,rson=0;
lson=build(l,mid-1);
int u=newtree(arr[mid]);
rson=build(mid+1,r);
if (lson){
t[u].son[0]=lson;
t[lson].fa=u;
}
if (rson){
t[u].son[1]=rson;
t[rson].fa=u;
}
pushup(u);
// debug();
return u;
}
int getnum(int k){//找第k個數
int u=root;
while(1){
pushdown(u);
if (k==t[t[u].son[0]].siz+1){
break;
}
else if (k<=t[t[u].son[0]].siz){
u=t[u].son[0];
}
else{
k=k-t[t[u].son[0]].siz-1;
u=t[u].son[1];
}
}
return u;
}
void reverse(int l,int r){//旋轉操作
l=getnum(l);
r=getnum(r+2);
splay(l,0);
splay(r,l);
int revu=t[r].son[0];
if (!revu){
return;
}
swap(t[revu].son[0],t[revu].son[1]);
swap(t[revu].maxl,t[revu].maxr);
t[revu].p^=1;
pushup(r);
pushup(l);
return;
}
void insert(int k,int l,int r){//插入操作
splay(getnum(k+2),0);
splay(getnum(k+1),root);
int u=build(l,r);
t[t[root].son[0]].son[1]=u;
t[u].fa=t[root].son[0];
pushup(t[root].son[0]);
pushup(root);
return;
}
void del(int &u){
if (!u){
return;
}
q.push(u);
t[u].fa=0;
del(t[u].son[0]);
del(t[u].son[1]);
t[u].maxsub=t[u].maxl=t[u].maxr=-INF;
u=0;
return;
}
void find_del(int l,int r){//刪除操作
l=getnum(l);
r=getnum(r+2);
splay(l,0);
splay(r,root);
del(t[r].son[0]);
pushup(r);
pushup(l);
return;
}
void setnum(int l,int r,int v){//makesame操作
l=getnum(l);
r=getnum(r+2);
splay(l,0);
splay(r,l);
int covu=t[r].son[0];
if (!covu){
return;
}
t[covu].set=t[covu].val=v;
t[covu].sumv=v*t[covu].siz;
t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(v,t[covu].sumv);
pushup(r);
pushup(l);
return;
}
int querymax(int l,int r){//兩個詢問操作
l=getnum(l);
r=getnum(r+2);
splay(l,0);
splay(r,root);
return t[t[r].son[0]].maxsub;
}
int querysum(int l,int r){
l=getnum(l);
r=getnum(r+2);
splay(l,0);
splay(r,root);
return t[t[r].son[0]].sumv;
}
int main(){
int n,m,x,y,z;
char s[15];
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
arr[0]=arr[n+1]=0;
t[0].maxl=t[0].maxr=t[0].maxsub=-INF;
root=build(0,n+1);
// debug();
for (int i=0;i<m;i++){
scanf("%s",&s);
if (s[0]=='I'){
scanf("%d%d",&x,&y);
for (int i=1;i<=y;i++){
scanf("%d",&arr[i]);
}
insert(x,1,y);
}
else if (s[0]=='D'){
scanf("%d%d",&x,&y);
find_del(x,x+y-1);
}
else if (s[0]=='M' && s[2]=='K'){
scanf("%d%d%d",&x,&y,&z);
setnum(x,x+y-1,z);
}
else if (s[0]=='R'){
scanf("%d%d",&x,&y);
reverse(x,x+y-1);
}
else if (s[0]=='G' && s[3]=='-'){
scanf("%d%d",&x,&y);
printf("%d\n",querysum(x,x+y-1));
}
else if (s[0]=='G'){
scanf("%d",&x);
printf("%d\n",t[getnum(x+1)].val);
}
else{
scanf("%d%d",&x,&y);
printf("%d\n",querymax(x,x+y-1));
}
// debug();
}
}