动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值。
感觉有点难写。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-6; const double PI = acos(-1); int Log[N]; int MIN = inf; struct ST { int dp[N][20], ty; void build(int n, int b[], int _ty) { ty = _ty; for(int i = -(Log[0]=-1); i < N; i++) Log[i] = Log[i - 1] + ((i & (i - 1)) == 0); for(int i = 1; i <= n; i++) dp[i][0] = ty * b[i]; for(int j = 1; j <= Log[n]; j++) for(int i = 1; i + (1 << j) - 1 <= n; i++) dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } int query(int x, int y) { int k = Log[y - x + 1]; return ty * max(dp[x][k], dp[y - (1 << k) + 1][k]); } } rmq; int n, k, q, a[N]; #define lson l, mid, a[x].ls #define rson mid + 1, r, a[x].rs namespace SGT1 { int tot, Rt; struct Node { Node() { mn = inf; ls = rs = 0; lazy = inf; } int mn, ls, rs, lazy; } a[N * 25]; inline void pull(int x) { a[x].mn = min(a[a[x].ls].mn, a[a[x].rs].mn); } inline void push(int x) { if(a[x].lazy < inf) { if(!a[x].ls) a[x].ls = ++tot; if(!a[x].rs) a[x].rs = ++tot; int lazy = a[x].lazy, l = a[x].ls, r = a[x].rs; a[l].mn = lazy; a[r].mn = lazy; a[l].lazy = lazy; a[r].lazy = lazy; a[x].lazy = inf; } } void update(int L, int R, int val, int l, int r, int& x) { if(!x) x = ++tot; if(l >= L && r <= R) { a[x].mn = val; a[x].lazy = val; return; } push(x); int mid = l + r >> 1; if(L <= mid) update(L, R, val, lson); if(R > mid) update(L, R, val, rson); pull(x); } int query(int L, int R, int l, int r, int x) { if(l >= L && r <= R) return a[x].mn; push(x); int mid = l + r >> 1; if(R <= mid) return query(L, R, lson); else if(L > mid) return query(L, R, rson); else return min(query(L, R, lson), query(L, R, rson)); } } namespace SGT2 { int tot, Rt; struct Node { Node() { ls = rs = 0; mn = inf; vis = false; } int mn, ls, rs; bool vis; } a[N * 25]; void update(int L, int R, int l, int r, int& x) { if(!x) { x = ++tot; if(r - l + 1 >= n) a[x].mn = MIN; else { int be = (l - 1) % n + 1; int ed = be + (r - l); a[x].mn = rmq.query(be, ed); } } if(a[x].vis) return; if(l >= L && r <= R) { a[x].mn = inf; a[x].vis = true; return; } int mid = l + r >> 1; if(R <= mid) { update(L, R, lson); if(!a[x].rs) { a[x].rs = ++tot; if(r - mid >= n) { a[a[x].rs].mn = MIN; } else { int be = (mid) % n + 1; int ed = be + (r - mid) - 1; a[a[x].rs].mn = rmq.query(be, ed); } } } else if(L > mid) { update(L, R, rson); if(!a[x].ls) { a[x].ls = ++tot; if(mid - l + 1 >= n) { a[a[x].ls].mn = MIN; } else { int be = (l - 1) % n + 1; int ed = be + (mid - l); a[a[x].ls].mn = rmq.query(be, ed); } } } else { update(L, R, lson); update(L, R, rson); } a[x].mn = min(a[a[x].ls].mn, a[a[x].rs].mn); } int query(int L, int R, int l, int r, int& x) { if(!x) { x = ++tot; if(r - l + 1 >= n) a[x].mn = MIN; else { int be = (l - 1) % n + 1; int ed = be + (r - l); a[x].mn = rmq.query(be, ed); } } if(a[x].vis) return inf; if(l >= L && r <= R) return a[x].mn; int mid = l + r >> 1; if(R <= mid) return query(L, R, lson); else if(L > mid) return query(L, R, rson); else return min(query(L, R, lson), query(L, R, rson)); } } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); a[i + n] = a[i]; MIN = min(MIN, a[i]); } rmq.build(2 * n, a, -1); scanf("%d", &q); while(q--) { int op; scanf("%d", &op); if(op == 1) { int L, R, x; scanf("%d%d%d", &L, &R, &x); SGT1::update(L, R, x, 1, n * k, SGT1::Rt); SGT2::update(L, R, 1, n * k, SGT2::Rt); } else { int L, R; scanf("%d%d", &L, &R); printf("%d\n", min(SGT1::query(L, R, 1, n * k, SGT1::Rt), SGT2::query(L, R, 1, n * k, SGT2::Rt))); } } return 0; } /* */