版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvzelong2014/article/details/83591323
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;
}