>Link
luogu P6242
>Description
>解题思路
这个大佬写的好好%%
对于每个节点,我们维护:当前最大值,当前次大值,历史最大值,历史次大值(这道题好像不用用到这个),当前最大值的个数,区间和,和四个懒标记
四个懒标记分别为:
- lazy1:当前最大值要加上的值
- lazy2:历史最大值要加上的值
- lazy3:当前非最大值要加上的值
- lazy4:历史非最大值要加上的值
加操作:全部都加上
取min操作:考虑要取的min值 v a l val val的不同情况。 v a l val val值大于等于当前区间的最大值,不用更新; v a l val val小于最大值,且大于等于次大值,那我们就只用更新最大值的那几个数为 v a l val val,设最大值 m a x a maxa maxa的个数为 c n t cnt cnt,区间和就减去 c n t ∗ ( m a x a − v a l ) cnt*(maxa-val) cnt∗(maxa−val);否则就继续递归下去
剩下的操作就是常规的线段树操作
具体操作看代码吧QAQ
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
#define LL long long
#define inf 1000000000
#define l1(k) t[k].lazy1
#define l2(k) t[k].lazy2
#define l3(k) t[k].lazy3
#define l4(k) t[k].lazy4
#define ma(k) t[k].maxa
#define p(k) t[k].pre
#define mb(k) t[k].maxb
#define cnt(k) t[k].cnt
#define l(k) t[k].l
#define r(k) t[k].r
#define sum(k) t[k].sum
using namespace std;
struct tree
{
LL l, r, maxa, pre, maxb, cnt;
LL lazy1, lazy2, lazy3, lazy4;
LL sum;
} t[N * 10];
int n, m;
LL a[N];
int read ()
{
int ret = 0;
char cc = getchar(), zf = ' ';
while (cc < '0' || cc > '9') zf = cc, cc = getchar();
while (cc >= '0' && cc <= '9')<