Description

农夫Byteasar买了一片n亩的土地,他要在这上面种草。
他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘米。
Byteasar一共会进行m次收割,其中第i次收割在第d[i]天,并把所有高度大于等于b[i]的部分全部割去。Byteasar想知道,每次收割得到的草的高度总和是多少,你能帮帮他吗?
 

Input

第一行包含两个正整数n,m(1<=n,m<=500000),分别表示亩数和收割次数。
第二行包含n个正整数,其中第i个数为a[i](1<=a[i]<=1000000),依次表示每亩种植的草的生长能力。
接下来m行,每行包含两个正整数d[i],b[i](1<=d[i]<=10^12,0<=b[i]<=10^12),依次描述每次收割。
数据保证d[1]<d[2]<...<d[m],并且任何时刻没有任何一亩草的高度超过10^12。
 

Output

输出m行,每行一个整数,依次回答每次收割能得到的草的高度总和。
 

Sample Input

4 4
1 2 4 3
1 1
2 2
3 0
4 4

Sample Output

6
6
18
0

HINT

第1天,草的高度分别为1,2,4,3,收割后变为1,1,1,1。
第2天,草的高度分别为2,3,5,4,收割后变为2,2,2,2。
第3天,草的高度分别为3,4,6,5,收割后变为0,0,0,0。
第4天,草的高度分别为1,2,4,3,收割后变为1,2,4,3。
 
不难发现无论何时草高度从小到大的顺序是不变的,我们可以按生长速度先排序一下。
然后问题就比较简单了,一次收割其实类似一个区间覆盖,我们只需找到第一个被收割的草即可。
用线段树维护区间最后一棵草上次被收割的时间、上次剩多长、所有草高度和减去时间*生长高度之和,很容易就O(logn)了。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
typedef long long ll;
inline ll read() {
ll x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=500010;
int n,m,A[maxn];
ll setv[maxn<<2],sett[maxn<<2],suma[maxn<<2],sumv[maxn<<2],maxv[maxn<<2],maxt[maxn<<2];
void maintain(int o,int l,int r) {
int lc=o<<1,rc=lc|1;
if(setv[o]>=0) {
sumv[o]=setv[o]*(r-l+1)-sett[o]*suma[o];
maxv[o]=setv[o];maxt[o]=sett[o];
}
else if(l<r) {
sumv[o]=sumv[lc]+sumv[rc];
maxv[o]=maxv[rc];maxt[o]=maxt[rc];
}
}
void pushdown(int o,int l,int r) {
int lc=o<<1,rc=lc|1,mid=l+r>>1;
if(setv[o]>=0) {
setv[lc]=setv[rc]=setv[o];
sett[lc]=sett[rc]=sett[o];
maxt[lc]=maxt[rc]=sett[o];
sumv[lc]=setv[o]*(mid-l+1)-sett[o]*suma[lc];
sumv[rc]=setv[o]*(r-mid)-sett[o]*suma[rc];
maxv[lc]=maxv[rc]=setv[o];
setv[o]=sett[o]=-1;
}
}
void build(int o,int l,int r) {
if(l==r) suma[o]=A[l];
else {
setv[o]=-1;
int mid=l+r>>1,lc=o<<1,rc=lc|1;
build(lc,l,mid);build(rc,mid+1,r);
suma[o]=suma[lc]+suma[rc];
}
}
ll ans,d,b;
int findst(int o,int l,int r) {
if(l==r) return l;
else {
pushdown(o,l,r);
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(maxv[lc]+(d-maxt[lc])*A[mid]>b) return findst(lc,l,mid);
return findst(rc,mid+1,r);
}
}
void update(int o,int l,int r,int ql,int qr) {
if(ql<=l&&r<=qr) {
ans+=sumv[o]+d*suma[o]-b*(r-l+1);
setv[o]=b;sett[o]=d;
}
else {
pushdown(o,l,r);
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(ql<=mid) update(lc,l,mid,ql,qr);
if(qr>mid) update(rc,mid+1,r,ql,qr);
}
maintain(o,l,r);
}
int main() {
n=read();m=read();
rep(i,1,n) A[i]=read();
sort(A+1,A+n+1);
build(1,1,n);
rep(i,1,m) {
d=read();b=read();
if(maxv[1]+(d-maxt[1])*A[n]<=b) puts("0");
else {
int s=findst(1,1,n);ans=0;
update(1,1,n,s,n);printf("%lld\n",ans);
}
}
return 0;
}

  

BZOJ4293: [PA2015]Siano的更多相关文章

  1. BZOJ4293 [PA2015]Siano(线段树)

    传送门 这Seg确实不好写,不过因为它与ai的相对顺序无关,所以,我们在对ai排序之后,就可做了.维护一个区间最大值,维护一个和,维护一个区间赋值的懒标记,再维护一个时间变化的标记就可以了. 因为不论 ...

  2. 【BZOJ4293】[PA2015]Siano 线段树

    [BZOJ4293][PA2015]Siano Description 农夫Byteasar买了一片n亩的土地,他要在这上面种草. 他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会 ...

  3. 2018.07.23[PA2015]Siano(线段树)

    [PA2015]Siano 描述 Description 农夫Byteasar买了一片n亩的土地,他要在这上面种草. 他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘 ...

  4. BZOJ.4293.[PA2015]Siano(线段树)

    题目链接 \(Description\) 有一片n亩的土地,要在这上面种草. 在每一亩土地上都种植了一种独一无二的草,其中,第\(i\)亩土地的草每天会长高\(a[i]\)厘米. 一共会进行\(m\) ...

  5. 【BZOJ】4293: [PA2015]Siano 线段树上二分

    [题意]给定n棵高度初始为0的草,每天每棵草会长高a[i],m次收割,每次在d[i]天将所有>b[i]的草收割到b[i],求每次收割量.n<=500000. [算法]线段树上二分 [题解] ...

  6. [PA2015]Siano 单调栈

    由于某人找了个单调栈的题解但是没研究透所以让我们来研究............ 首先先来考虑下面一种情况,假设第\(k\)次切割时,天数为\(d_k\),高度为\(b_k\),第\(k+1\)次切割时 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. 【bzoj4293】【PA2015】Siano

    如题,首先可以考虑相对大小是不变的. 那么先sort,之后每次在线段树上二分即可. #include<bits/stdc++.h> typedef long long ll; using ...

  9. BZOJ 4291: [PA2015]Kieszonkowe 水题

    4291: [PA2015]Kieszonkowe Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnli ...

随机推荐

  1. composer 报错:Your requirements could not be resolved to an installable set of packages 解决方法

    composer 报错: - Your requirements could not be resolved to an installable set of packages xxxxxxxxxxx ...

  2. org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [XXX] in DispatcherServlet with name 'springMVC'

    在web.xml中添加 <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern ...

  3. python正则表达式re

    Python正则表达式: re 正则表达式的元字符有. ^ $ * ? { [ ] | ( ).表示任意字符[]用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字符集,对于字符集中的字符可 ...

  4. sh3.useradd 添加用户脚本

    1.写一个脚本: 添加10个用户user1到user10,密码同用户名,但要求只有用户不存在的情况下才能添加 #/bin/bash # ..};do if id user$i &> /d ...

  5. windows+ant+git+tomcat中ant直接获取git项目部署注意点

    最近项目搬迁到公司的"GitHub"上面原来的SVN的ant发布脚本要改下,于是百度ant获取git的方法太少了,windows平台上更是没有所以搞了两天,今天终于有点成果分享给大 ...

  6. css经典布局——头尾固定高度中间高度自适应布局

    转载:穆乙 http://www.cnblogs.com/pigtail/ 相信做过后台管理界面的同学,都非常清楚这个布局.最直观的方式是框架这个我不想多写费话,因为我们的重心不在这里.如果有不了解的 ...

  7. Python下Json和Msgpack序列化比较

     最近用Python时,遇到了序列化对象的问题,传统的json和新型序列化工具包msgpack都有涉及,于是做一个简单的总结: 通俗的讲:序列化:将对象信息转化为可以存储或传输的形式:反序列化:把这个 ...

  8. RakNet发送与接收数据

    http://www.jenkinssoftware.com/raknet/manual/creatingpackets.html Creating Packets with Bitstreams W ...

  9. 原生js焦点轮播图

    原生js焦点轮播图主要注意这几点: 1.前后按钮实现切换,同时注意辅助图2.中间的button随着前后按钮对应切换,同时按button也能跳转到相应的index3.间隔调用与无限轮播.4.注意在动画时 ...

  10. Linux 系统中堆栈的使用方法

    本节内容概要描述了Linux内核从开机引导到系统正常运行过程中对堆栈的使用方式.这部分内容的说明与内核代码关系比较密切,可以先跳过.在开始阅读相应代码时再回来仔细研究. Linux 0.12系统中共使 ...