luogu4891序列 線段樹
阿新 • • 發佈:2018-11-06
luoguP4891 序列
題目傳送門
分析
神仙線段樹。
被各種優美的暴力吊打。
首先
陣列的修改操作顯然是可以暴力的,因為一旦取到了
,由於修改操作是單調的,
的修改肯定不會再影響到這個取到的
。
其次是
的修改,線段樹中維護
,這樣的話再線段樹上二分之後相當於是區間賦值操作。
分析一波之後的核心就是要如何保證改修改的修改,不該修改的不修改。
維護的值
有些取
,有些取
,所以乾脆維護
和
的乘積(分開維護)。
既然維護的是
,那麼肯定要維護
的值。
再考慮
的暴力。如果某次
的值修改得比
的大,那麼要去暴力找到那個需要取到最小值的
,所以維護
的最小值,如果需要修改就暴力進入那個區間。
最後由於區間賦值操作,所以肯定要有一個
由於需要計算賦值時候的乘積,所以需要維護一個
表示
取到
的個數。
操作的時候大力分類+維護即可。
複雜度
,因為賦值的時候要快速冪
程式碼
指標真好玩~
#include<bits/stdc++.h>
const int N = 1e5 + 10, P = 1e9 + 7, inf = 1e9;
int ri() {
char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int a[N], b[N];
int Pow(int x, int k) {
int r = 1;
for(;k; x = 1LL * x * x % P, k >>= 1) if(k & 1) r = 1LL * r * x % P;
return r;
}
struct Node {
int ma, mb, ta, tb, cnt; bool tag; Node *ls, *rs;
void Init(int A, int B) {
ma = A; mb = B;
(cnt = A < B) ? ta = A, tb = 1 : (tb = B, mb = inf, ta = 1);
}
void Tag(int v) {ma = v; ta = Pow(v, cnt); tag = true;}
void Dw() {if(tag) ls->Tag(ma), rs->Tag(ma), tag = false;}
void Up() {
ma = std::max(ls->ma, rs->ma);
mb = std::min(ls->mb, rs->mb);
ta = 1LL * ls->ta * rs->ta % P;
tb = 1LL * ls->tb * rs->tb % P;
cnt = ls->cnt + rs->cnt;
}
void Build(int L, int R) {
if(L == R) {
ma = a[L]; mb = b[L];
(cnt = a[L] < b[L]) ? (ta = ma, tb = 1) : (tb = mb, mb = inf, ta = 1);
return ;
}
int m = L + R >> 1;
(ls = new Node)->Build(L, m);
(rs = new Node)->Build(m + 1, R);
Up();
}
void UpB(int L, int R, int v, int w) {
if(L == R) return Init(ma, w);
Dw(); int m = L + R >> 1;
v <= m ? ls->UpB(L, m, v, w) : rs->UpB(m + 1, R, v, w);
Up();
}
void UpA(int L, int R, int w) {
if(w < mb) return Tag(w);
if(L == R) return Init(w, mb);
Dw(); int m = L + R >> 1;
ls->UpA(L, m, w); rs->UpA(m + 1, R, w);
Up();
}
void Bound(int L, int R, int v, int w) {
if(v == L && ma < w) return UpA(L, R, w);
if(L == R) return ;
Dw(); int m = L + R >> 1;
if(v > m) return rs->Bound(m + 1, R, v, w), Up();
if(ls->ma < w) rs->Bound(m + 1, R, m + 1, w);
ls->Bound(L, m, v, w);
Up();
}
}rt;
int main() {
int n = ri(), q = ri();
for(int i = 1;i <= n; ++i) a[i] = std::max(a[i - 1], ri());
for(int i = 1;i <= n; ++i) b[i] = ri();
rt.Build(1, n);
for(;q--;) {
int op = ri(), x = ri(), y = ri();
op ? rt.UpB(1, n, x, y) : rt.Bound(1, n, x, y);
printf("%d\n", 1LL * rt.ta * rt.tb % P);
}
return 0;
}