题意:
(n)个草,第(0)天种下,高度都为(0),每个草每天长高(a_i)。现给出(q)询问,每次给出第(b_i)天,然后把高于(d_i)的全削成(d_i),每次问你此次削下来的高度是多少,(b_{i-1}<b_i)。
思路:
能看出草的顺序和答案无关,那么按(a_i)排序,后面的草永远都比前面的高。然后线段树维护区间加,区间重置,区间询问。
代码:
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<bitset>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e5 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const ll MOD = 1000000007;
#define lson (rt << 1)
#define rson (rt << 1 | 1)
int n, m;
ll sum[maxn << 2], sumW[maxn << 2], Mw[maxn << 2], Max[maxn << 2];
ll t[maxn << 2], reset[maxn << 2];
//时间戳,重置
ll a[maxn];
void pushup(int rt){
sum[rt] = sum[lson] + sum[rson];
Max[rt] = Max[rson];
Mw[rt] = Mw[rson];
sumW[rt] = sumW[lson] + sumW[rson];
}
void pushdown(int rt, int l, int r){
int m = (l + r) >> 1;
if(reset[rt] != -1){
reset[lson] = reset[rt];
reset[rson] = reset[rt];
t[lson] = 0;
t[rson] = 0;
Max[lson] = reset[rt];
Max[rson] = reset[rt];
sum[lson] = 1LL * reset[rt] * (m - l + 1);
sum[rson] = 1LL * reset[rt] * (r - m);
reset[rt] = -1;
}
if(t[rt]){
sum[lson] += t[rt] * sumW[lson];
sum[rson] += t[rt] * sumW[rson];
Max[lson] += t[rt] * Mw[lson];
Max[rson] += t[rt] * Mw[rson];
t[lson] += t[rt];
t[rson] += t[rt];
t[rt] = 0;
}
}
void build(int l, int r, int rt){
t[rt] = 0;
reset[rt] = -1;
if(l == r){
sumW[rt] = Mw[rt] = a[l];
sum[rt] = Max[rt] = 0;
return;
}
int m = (l + r) >> 1;
build(l, m, lson);
build(m + 1, r, rson);
pushup(rt);
}
void _set(int L, int R, int l, int r, ll v, int rt){
if(L <= l && R >= r){
sum[rt] = 1LL * v * (r - l + 1);
reset[rt] = v;
Max[rt] = v;
t[rt] = 0;
return;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
_set(L, R, l, m, v, lson);
if(R > m)
_set(L, R, m + 1, r, v, rson);
pushup(rt);
}
void add(int L, int R, int l, int r, ll v, int rt){
if(L <= l && R >= r){
sum[rt] += sumW[rt] * v;
t[rt] += v;
Max[rt] += Mw[rt] * v;
return;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
add(L, R, l, m, v, lson);
if(R > m)
add(L, R, m + 1, r, v, rson);
pushup(rt);
}
ll querysum(int L, int R, int l, int r, int rt){
if(L <= l && R >= r){
return sum[rt];
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
ll ret = 0;
if(L <= m)
ret += querysum(L, R, l, m, lson);
if(R > m)
ret += querysum(L, R, m + 1, r, rson);
return ret;
}
int queryMore(int l, int r, ll v, int rt){
if(l == r){
return Max[rt] > v? l : -1;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if(Max[lson] > v)
return queryMore(l, m, v, lson);
else
return queryMore(m + 1, r, v, rson);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
sort(a + 1, a + n + 1);
build(1, n, 1);
ll u, v, pre = 0;
while(m--){
scanf("%lld%lld", &u, &v);
add(1, n, 1, n, u - pre, 1);
int pos = queryMore(1, n, v, 1);
if(pos == -1) puts("0");
else{
ll ret = querysum(pos, n, 1, n, 1);
ret = ret - 1LL * v * (n - pos + 1);
printf("%lld
", ret);
_set(pos, n, 1, n, v, 1);
}
pre = u;
}
return 0;
}