給你乙個長度為n的序列和m個操作
1.查詢第k個數的值
2.將第k個數增加d
3.查詢一段區間的和
4.查詢一段區間的最大值
5.將一段區間鏡面翻轉(例如序列,將從2到5的區間翻轉後得到序列)
對於除操作2,5以外的操作,輸出相應的答案
第一行兩個正整數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的這個區間
除操作2,5外每個操作輸出佔一行,乙個整數,為本次提問的答案
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
4 14
2 10
62<=n<=100000
1<=m<=100000
原序列1<=ai<=1000
每次1<=k<=n,1<=l<=r<=n,1<=d<=1000
我們維護一棵平衡樹,鍵值為各點的編號。乙個點的左子樹的實際位置在這個點之前,右子樹的實際位置在這個點之後。初始時任一點的左子樹(如果有的話)編號全部小於該點編號,右子樹編號全部大於該點編號。並記錄好每個點為根的樹的最大元素、元素和。
一號操作,我們只用類似於平衡樹「查詢第k小」的方法就可以了。
二號,先將這個點找到(見一號操作),再旋到根。這樣,修改操作就只會對根節點有影響了。
三號,找到第(l-1)個數的編號,旋到根。再找到第(r+1)個數,旋到根的右兒子。輸出(r+1)個數的左兒子的元素和就行了(解釋略)。
四號同三號。
五號,略同三號,在(r+1)個數的左兒子打乙個lazy標記,以後討論到帶標記的點就交換左右兒子並下放標記。由於偶數個標記不影響結果,建議使用異或修改標記。
用的splay
#include #include #include using namespace std;
const int q=100005;
int si[q],ls[q],rs[q],f[q],v[q],maxn[q],sum[q],root=1,n,ch[q]=;
void lx(int x)
void rx(int x)
void pd(int x)
void splay(int x,int
goal)
else
}if(f[x]==0)root=x;
}int gk(int k)
return p;
}int main()
else
if(ls[x])x=ls[x];
else
}f[i]=x;
splay(i,0);
}while(m--)
if(i==3||i==4)
if(i==5)
}return
0;}
區間翻轉問題 Splay
問題描述 給你乙個長度為n的序列和m個操作 1.查詢第k個數的值 2.將第k個數增加d 3.查詢一段區間的和 4.查詢一段區間的最大值 5.將一段區間鏡面翻轉 例如序列,將從2到5的區間翻轉後得到序列 對於除操作2,5以外的操作,輸出相應的答案 輸入格式 第一行兩個正整數n,m 第二行n個整數,為初...
Splay之區間翻轉問題
給你 n 個數 分別為 1,2,3,4 n 然後有 m 個操作,每個操作對應一段區間,將區間的數進行翻轉。比如 1,2,3,4,5 這段序列 操作區間為 2 4 翻轉完成後的序列為 1,4,3,2,5 第一行分別輸入 n,m 第2行到m 1行每行輸入兩個數 對應操作的區間 輸出最後翻轉完成後的序列 ...
4975 區間翻轉
小q和tangjz正在乙個長度為n的序列a 1,a 2,a n上玩乙個有趣的關於區間翻轉的遊戲。小q和tangjz輪流行動 小q先手。每次行動方玩家需要選擇乙個長度為4x 2或4x 3的區間 l,r 1 l r n 其中x是該玩家自行選擇 的非負整數,然後將a l,a a a r翻轉,例如1 3 2...