【BZOJ4293】[PA2015]Siano

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。

题解:有一个容易发现的性质:长得快的草永远不会比长得慢的草矮。

所以先按ai排序,然后每次只需要二分一个边界,长得比这个边界快的草都会被割掉。然后用线段树维护即可。

但是具体实现不是那么方便,我们的线段树需要维护:带系数的区间加,区间赋值,区间求和,区间求最大值。细节还是看代码吧~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int maxn=500010;
int n,m;
ll A[maxn],B,D[maxn],s[maxn<<2],sm[maxn<<2],siz[maxn<<2],ts[maxn<<2],tag[maxn<<2];
void pushup(int x)
{
s[x]=s[lson]+s[rson],sm[x]=min(sm[lson],sm[rson]);
}
void pushdown(int l,int r,int x)
{
int mid=l+r>>1;
if(~tag[x])
{
ts[lson]=ts[rson]=0,tag[lson]=tag[rson]=sm[lson]=sm[rson]=tag[x];
s[lson]=(mid-l+1)*tag[x],s[rson]=(r-mid)*tag[x];
tag[x]=-1;
}
if(ts[x])
{
ts[lson]+=ts[x],ts[rson]+=ts[x];
s[lson]+=siz[lson]*ts[x],sm[lson]+=A[l]*ts[x],s[rson]+=siz[rson]*ts[x],sm[rson]+=A[mid+1]*ts[x];
ts[x]=0;
}
}
void build(int l,int r,int x)
{
tag[x]=-1;
if(l==r)
{
siz[x]=A[l];
return ;
}
int mid=l+r>>1;
build(l,mid,lson),build(mid+1,r,rson);
siz[x]=siz[lson]+siz[rson];
}
ll updata(int l,int r,int x,int a,int b,ll c)
{
if(a<=l&&r<=b)
{
ll ret=s[x]-(r-l+1)*c;
ts[x]=0,sm[x]=tag[x]=c,s[x]=(r-l+1)*c;
return ret;
}
pushdown(l,r,x);
int mid=l+r>>1;
ll ret=0;
if(a<=mid) ret+=updata(l,mid,lson,a,b,c);
if(b>mid) ret+=updata(mid+1,r,rson,a,b,c);
pushup(x);
return ret;
}
int getpre(int l,int r,int x,ll a)
{
if(sm[x]>=a) return l-1;
if(l==r) return l;
pushdown(l,r,x);
int mid=l+r>>1;
if(sm[rson]<a) return getpre(mid+1,r,rson,a);
return getpre(l,mid,lson,a);
}
ll rd()
{
ll ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd();
int i;
for(i=1;i<=n;i++) A[i]=rd();
sort(A+1,A+n+1);
build(1,n,1);
for(i=1;i<=m;i++)
{
D[i]=rd(),B=rd();
ts[1]+=D[i]-D[i-1],s[1]+=siz[1]*(D[i]-D[i-1]),sm[1]+=A[1]*(D[i]-D[i-1]);
int a=getpre(1,n,1,B);
if(a<n) printf("%lld\n",updata(1,n,1,a+1,n,B));
else printf("0\n");
}
return 0;
}//4 4 1 2 4 3 1 1 2 2 3 0 4 4

【BZOJ4293】[PA2015]Siano 线段树的更多相关文章

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

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

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

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

  3. BZOJ4293: [PA2015]Siano

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

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

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

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

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

  6. [火星补锅] siano 神奇的线段树

    前言: 本来以为很难打的,没想到主干一次就打对了,然而把输入的b和d弄混了,这sb错误调了两个小时... 解析: 神奇的线段树.注意到有一个性质,无论怎么割草,生长速度快的一定不会比生长速度慢的矮.因 ...

  7. 2018.07.25 bzoj3878: [Ahoi2014&Jsoi2014]奇怪的计算器(线段树)

    传送门 线段树综合. 让我想起一道叫做siano" role="presentation" style="position: relative;"&g ...

  8. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  9. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

随机推荐

  1. 【Visual Studio】VS2013的Release模式下进行调试(转)

    原文转自 http://blog.csdn.net/haizimin/article/details/50262901 在有的情况下,我们可能不能直接利用Debug模式进行程序调试,那么如何在Rele ...

  2. 转 python语法学习面向对象之继承

    传送门 python语法学习面向对象之继承 只要涉及到面向对象,”类“是必须出现的一个代名词. 类和对象是面向对象编程的两个主要方面.类创建一个新类型,而对象是这个类的实例. 类的一些概念: 包括初始 ...

  3. Linux 之 MySQL主从同步

    MySQL主从同步 参考教程:[千峰教育] 1.架设两个虚拟服务器,都安装好mysql. 2.关闭防火墙和Selinux. service iptables stop setenforce 0 3.修 ...

  4. yii加载自带验证码的方法

    Yii的源码包里面是自带有验证码的相关类的,因此在使用验证码的时候无需再加载外部验证码类来助阵了.下面本文将介绍一下如何在项目中加载Yii自带的验证码功能. 具体分三步: (1)在需要加载验证码的co ...

  5. git add 错误修改方法

    git add a.txt 报如下错误: fatal: Unable to create 'E:/git/.git/index.lock': File exists. Another git proc ...

  6. 快速上手 Echarts

    最近使用到了 百度的 Echarts 数据可视化工具,这里简单介绍如何快速上手. 一.下载 这里选择目前最新版本,4.2.1 地址:https://github.com/apache/incubato ...

  7. 分享Kali Linux 2017年第12周镜像文件

    分享Kali Linux 2017年第12周镜像文件 Kali Linux官方于3月19日发布2017年的第12周镜像.这次维持了11个镜像文件的规模.默认的Gnome桌面的4个镜像,E17.KDE. ...

  8. SQL Server 监控系列 —— 二

    http://www.cnblogs.com/bhtfg538/archive/2011/01/21/1939706.html

  9. [转] 32位 PL/SQL Develope r如何连接64位的Oracle 图解

    原文地址:LINK 由于硬件技术的不断更新,Win7系统逐渐成为主流,而且计算机内存逐渐增大,为了充 分的利用内存资源(因为32为系统最多只能用到3G左右的内存),提高系统性能,很多人开始使用Win7 ...

  10. 邁向IT專家成功之路的三十則鐵律 鐵律十四:IT人言談之道-守中

    人與人之間的互動交談最重要的莫過於真誠與頃聽.老子曾在所著的道德經之中,言道:「多言數窮,不如守中」,其意思簡單來說就是不要說多餘的話.人與人之間的相處,常為了一個面子問題,你來我往的爭論不休,其實真 ...