題目大意:你要維護乙個長度為n的序列,進行操作。
對於這個序列,233之類的數不能出現,也就是說233,2333,23333,233333……這一系列的數不能在序列中出現。
1 i 輸出第i個元素。
2 a b x 將[a,b]區間的序列賦值為x。
3 a b x 將[a,b]區間的序列加上x。
4 a b 將區間[a,b]賦值為[a,b]中的最大值。
5 a b 將區間[a,b]賦值為[a,b]中的最小值。
6 a b 將區間[a,b]賦值為[a,b]中的平均值,平均值向下取整。
如果在操作後區間中出現了233之類的數,則需要將你剛才操作的那個區間的數全部加一,如果再出現,就再加一,直到不出現為止。
初始不會出現可怕的數字。資料範圍1e5,數值1e9+7。
題解:分級,相同的區間視為縮成乙個點,這樣複雜度不會超過兩個log。(其實平衡樹可以嚴格乙個log但是常數大反而跑得不是很快。)
#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<#define sp <<" "
#define ln typedef pair<
int,
int> pii;
typedef set<
int>
::iterator sit;
inline
intinn()
const lint inf=llong_max/10-
10;const
int n=
100010
;lint kp[20]
;int kpc,a[n]
;struct segment
*rt;
inline lint getnxt
(lint x)
inline
intpush_up
(segment*
&rt)
intbuild
(segment*
&rt,
int l,
int r)
inline
intupdate_tags
(segment*
&rt,lint v,
int tp)
else
return0;
}inline
intpush_down
(segment*
&rt)
else
if(rt->pt)
return0;
}int
update
(segment*
&rt,
int s,
int t,lint v,
int tp)
lint query
(segment*
&rt,
int s,
int t,
int tp)
if(midreturn ans;
}int
update_dis
(segment*
&rt,
int p)
inline
intadj
(int l,
int r)
return0;
}int
main()
int l=
inn(
),r=
inn();
if(tp<=
3) x=
inn();
else x=
query
(rt,l,r,tp-3)
;if(tp==
6) x/
=(r-l+1)
;if(tp==3)
update
(rt,l,r,x,2)
,adj
(l,r)
;else
update
(rt,l,r,
getnxt
(x)==x?x+
1:x,1)
;}return0;
}
序列操作(線段樹)
lxhgww 最近收到了乙個 01 序列,序列裡面包含了 n 1 n 105 個數,這些書要麼是 0,要麼是 1,現在對這個序列有五種變換操作和詢問操作 0 a b 把 a,b 區間內所有數全部變成 0。1 a b 把 a,b 區間內所有數全部變成 1。2 a b 把 a,b 區間內所有數全部取反,...
序列 線段樹
使用線段樹維護 b bb,初值為 bi b i bi 每次修改時,若乙個位置上的值變為了 0 00,則說明其會對答案產生新的貢獻,在外部使用樹狀陣列將貢獻計入答案,然後將該位置的值 重置為 bi b i bi 重置的時間複雜度是 o log n o log n o logn 考慮最壞情況,每次操作 ...
序列操作 BZOJ2962 線段樹
分析 資料範圍表示 c特別的小 c 20 我們可以考慮nlogn c 2的演算法。線段樹維護區間資訊 f i 表示在 l,r 這段區間中選擇i個數相乘的和。因此,我們可以將區間看成乙個點,在pushup的時候用揹包的方式更新父節點。仔細觀察發現這是卷積 剩下的就是一些優化了.附上 include i...