题意:
给定一个长为 n 的数组 a,有 m 个操作,①:0,x,y,t,令 a i = m i n ( a i , t ) , i ∈ [ x , y ] a_i = min(a_i, t),i∈[x, y] ai=min(ai,t),i∈[x,y];②:1,x,y,询问 max{ a x , a x + 1 , . . . , a y a_x, a_{x+1}, ..., a_y ax,ax+1,...,ay };③:2,x,y,询问 ∑ i = x y a i \sum_{i=x}^{y}a_i ∑i=xyai。(n, m <= 1e6)
链接:
https://vjudge.net/problem/HDU-5306
解题思路:
维护区间最大值、最大值个数、严格次大值及区间和,则对于一个取小操作,分三类:① t >= 最大值,直接返回;② 次大值 < t < 最大值,打上懒惰标记,更新最大值即可;③ t <= 次大值,递归更新。总复杂度可证为 O(mlogn),详见16年国家集训队论文集。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e6 + 5;
const int maxm = 2e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
ll mx[maxn << 2], mx2[maxn << 2];
ll sum[maxn << 2], cov[maxn << 2];
int a[maxn], num[maxn << 2];
int n, m;
void pushUp(int rt){
sum[rt] = sum[lson] + sum[rson];
if(mx[lson] == mx[rson]){
mx[rt] = mx[lson], num[rt] = num[lson] + num[rson];
mx2[rt] = max(mx2[lson], mx2[rson]);
}
else if(mx[lson] > mx[rson]){
mx[rt] = mx[lson], num[rt] = num[lson];
mx2[rt] = max(mx2[lson], mx[rson]);
}
else{
mx[rt] = mx[rson], num[rt] = num[rson];
mx2[rt] = max(mx[lson], mx2[rson]);
}
}
void build(int l, int r, int rt){
cov[rt] = -1;
if(l == r){
mx[rt] = a[l], mx2[rt] = -1;
sum[rt] = a[l], num[rt] = 1;
return;
}
int mid = gmid;
build(l, mid, lson);
build(mid + 1, r, rson);
pushUp(rt);
}
void pushDown2(int rt, int son){
if(cov[rt] >= mx[son]) return;
sum[son] -= num[son] * (mx[son] - cov[rt]);
mx[son] = cov[son] = cov[rt];
}
void pushDown(int rt){
if(cov[rt] != -1){
pushDown2(rt, lson);
pushDown2(rt, rson);
cov[rt] = -1;
}
}
void dfs(int l, int r, int rt, ll val){
if(val >= mx[rt]) return;
if(val > mx2[rt]){
cov[0] = val;
pushDown2(0, rt);
return;
}
int mid = gmid;
pushDown(rt);
dfs(l, mid, lson, val);
dfs(mid + 1, r, rson, val);
pushUp(rt);
}
void update(int l, int r, int rt, int L, int R, ll val){
if(val >= mx[rt]) return;
if(l >= L && r <= R){
if(val > mx2[rt]){
cov[0] = val;
pushDown2(0, rt);
return;
}
return dfs(l, r, rt, val);
}
int mid = gmid;
pushDown(rt);
if(L <= mid) update(l, mid, lson, L, R, val);
if(R > mid) update(mid + 1, r, rson, L, R, val);
pushUp(rt);
}
ll queryM(int l, int r, int rt, int L, int R){
if(l >= L && r <= R) return mx[rt];
int mid = gmid; ll ret = -1;
pushDown(rt);
if(L <= mid) ret = max(ret, queryM(l, mid, lson, L, R));
if(R > mid) ret = max(ret, queryM(mid + 1, r, rson, L, R));
return ret;
}
ll queryS(int l, int r, int rt, int L, int R){
if(l >= L && r <= R) return sum[rt];
int mid = gmid; ll ret = 0;
pushDown(rt);
if(L <= mid) ret += queryS(l, mid, lson, L, R);
if(R > mid) ret += queryS(mid + 1, r, rson, L, R);
return ret;
}
int main(){
// ios::sync_with_stdio(0); cin.tie(0);
int t; scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
build(1, n, 1);
while(m--){
int opt, x, y, z; scanf("%d%d%d", &opt, &x, &y);
if(opt == 0){
scanf("%d", &z);
update(1, n, 1, x, y, z);
}
else if(opt == 1){
ll ret = queryM(1, n, 1, x, y);
printf("%lld\n", ret);
}
else{
ll ret = queryS(1, n, 1, x, y);
printf("%lld\n", ret);
}
}
}
return 0;
}