农夫Byteasar买了一片n亩的土地,他要在这上面种草。
他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘米。
Byteasar一共会进行m次收割,其中第i次收割在第d[i]天,并把所有高度大于等于b[i]的部分全部割去。Byteasar想知道,每次收割得到的草的高度总和是多少,你能帮帮他吗?
将所有草的生长速度从小到大排序
可以发现每时每刻草的长度都一定是递增的
这也就是说每次割草一定是包含尾部连续的一段
二分+线段树就可以O(nlogn)了
思路很简单,代码很难写
tre[x].bet:区间最长的草的长度(很显然一定是区间最右边的那棵)
tre[x].t:区间最后一次被割的时间(很显然也一定是区间最右边的那棵草最后一次被割的时间)
tre[x].len:区间草被割掉的总长度(当前总长度当然就是tre[x].len+T*tre[x].v)
tre[x].v:区间草生长速度和(显然这个求出来之后不可能被改变)
temp[x]/time[x]:延时标记,被割后的长度/最后一次被割的时间
#include
#include
#include
using namespace std;
#define LL long long
typedef struct
{
LL v, len;
LL bet, t;
}Tree;
Tree tre[2020000];
LL T, Y, ans, a[500005], temp[2020000], time[2020000];
void Create(int l, int r, int x)
{
int m;
if(l==r)
{
tre[x].v = a[r];
return;
}
m = (l+r)/2;
temp[x] = time[x] = -1;
Create(l, m, x*2);
Create(m+1, r, x*2+1);
tre[x].v = tre[x*2].v+tre[x*2+1].v;
}
void Lazy(int l, int r, int x)
{
int m;
m = (l+r)/2;
tre[x*2].t = tre[x*2+1].t = time[x];
tre[x*2].bet = tre[x*2+1].bet = temp[x];
tre[x*2].len = temp[x]*(m-l+1)-time[x]*tre[x*2].v;
tre[x*2+1].len = temp[x]*(r-m)-time[x]*tre[x*2+1].v;
if(l!=r)
{
temp[x*2] = temp[x*2+1] = temp[x];
time[x*2] = time[x*2+1] = time[x];
}
time[x] = temp[x] = -1;
}
void Atonce(int l, int r, int x)
{
if(time[x]>=0)
{
tre[x].len = temp[x]*(r-l+1)-time[x]*tre[x].v;
tre[x].bet = temp[x];
tre[x].t = time[x];
}
else if(l!=r)
{
tre[x].len = tre[x*2].len+tre[x*2+1].len;
tre[x].bet = tre[x*2+1].bet;
tre[x].t = tre[x*2+1].t;
}
}
int Find(int l, int r, int x)
{
int m;
if(l==r)
return r;
m = (l+r)/2;
if(time[x]>=0)
Lazy(l, r, x);
if(tre[x*2].bet+(T-tre[x*2].t)*a[m]>Y)
return Find(l, m, x*2);
else
return Find(m+1, r, x*2+1);
}
void Update(int l, int r, int x, int c, int d)
{
int m;
if(l>=c && r<=d)
{
ans += tre[x].len+T*tre[x].v-Y*(r-l+1);
time[x] = T;
temp[x] = Y;
Atonce(l, r, x);
return;
}
if(time[x]>=0)
Lazy(l, r, x);
m = (l+r)/2;
if(c<=m)
Update(l, m, x*2, c, d);
if(d>=m+1)
Update(m+1, r, x*2+1, c, d);
Atonce(l, r, x);
}
int main(void)
{
int n, m, i, r;
scanf("%d%d", &n, &m);
for(i=1;i<=n;i++)
scanf("%lld", &a[i]);
sort(a+1, a+n+1);
Create(1, n, 1);
while(m--)
{
scanf("%lld%lld", &T, &Y);
if(tre[1].bet+(T-tre[1].t)*a[n]<=Y)
printf("0\n");
else
{
ans = 0;
r = Find(1, n, 1);
Update(1, n ,1, r, n);
printf("%lld\n", ans);
}
}
return 0;
}
/*
4 4
1 2 4 3
1 3
2 3
*/