BZOJ4293: [PA2015]Siano

好像这几天的SAM的博客都忘记更了 咕咕咕(有时间补上

言归正传 这个题主要的性质是 相对增长趋势不会发生变化 那我们根据操作的性质 可以得出 每个时刻都满足初始状态下增长趋势的相对大小关系 就是说初始值大的在接下来的时刻也一定会大因此我们可以按照这个方式去建线段树 然后维护每次查询后每个位置初始值即可 普通的线段树操作

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
//struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
//void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}
ll flag[MAXN<<2],add[MAXN<<2],minn[MAXN<<2],sum1[MAXN<<2],sum2[MAXN<<2],a[MAXN]; //sum1 cs sum2 zeng
void up(int x){
	minn[x]=min(minn[x<<1],minn[x<<1|1]);
	sum1[x]=sum1[x<<1]+sum1[x<<1|1];
	sum2[x]=sum2[x<<1]+sum2[x<<1|1];
}
void built(int rt,int l,int r){
	flag[rt]=-1;add[rt]=minn[rt]=sum1[rt]=0;
	if(l==r){sum2[rt]=a[l];return ;}
	int mid=(l+r)>>1;
	built(rt<<1,l,mid);
	built(rt<<1|1,mid+1,r);
	up(rt);
}
void push(int x,int l,int r){
	int mid=(l+r)>>1;
	if(flag[x]!=-1){
		add[x<<1]=add[x<<1|1]=0;flag[x<<1]=flag[x<<1|1]=flag[x];
		minn[x<<1]=minn[x<<1|1]=flag[x];sum1[x<<1]=1LL*(mid-l+1)*flag[x];sum1[x<<1|1]=1LL*(r-mid)*flag[x];
		flag[x]=-1;
	}
	if(add[x]!=0){
		add[x<<1]+=add[x];add[x<<1|1]+=add[x];minn[x<<1]+=1LL*add[x]*a[l];minn[x<<1|1]+=1LL*add[x]*a[mid+1];
		sum1[x<<1]+=sum2[x<<1]*add[x];sum1[x<<1|1]+=sum2[x<<1|1]*add[x];
		add[x]=0;
	}
}
void update1(int rt,int l,int r,int ql,int qr,ll t){
	if(ql<=l&&r<=qr){add[rt]+=t;minn[rt]+=1LL*t*a[l];sum1[rt]+=1LL*sum2[rt]*t;return ;}
	int mid=(l+r)>>1;
	push(rt,l,r);
	if(ql<=mid)update1(rt<<1,l,mid,ql,qr,t);
	if(qr>mid)update1(rt<<1|1,mid+1,r,ql,qr,t);
	up(rt);
}
void update2(int rt,int l,int r,int ql,int qr,ll t){
	if(ql<=l&&r<=qr){add[rt]=0;flag[rt]=t;minn[rt]=t;sum1[rt]=1LL*t*(r-l+1);return ;}
	int mid=(l+r)>>1;
	push(rt,l,r);
	if(ql<=mid)update2(rt<<1,l,mid,ql,qr,t);
	if(qr>mid)update2(rt<<1|1,mid+1,r,ql,qr,t);
	up(rt);
}
ll ans1,ans2,key,Time;int id;
void Find(int x,int l,int r){
	if(l==r){
		if(minn[x]+1LL*Time*a[l]>=key){ans1+=sum1[x];ans2+=sum2[x];id=l;}
		return ;
	}
	int mid=(l+r)>>1;
	push(x,l,r);
	if(minn[x<<1|1]+1LL*Time*a[mid+1]>=key){ans1+=sum1[x<<1|1];ans2+=sum2[x<<1|1];id=mid+1;Find(x<<1,l,mid);}
	else Find(x<<1|1,mid+1,r);
	up(x);
}
int main(){
	int n,m;n=read();m=read();
	for(int i=1;i<=n;i++)a[i]=read();
	sort(a+1,a+n+1);built(1,1,n);ll d,b,last=0;
	while(m--){
		d=read();b=read();Time=d-last;key=b;ans1=ans2=id=0;Find(1,1,n);
		if(!id){puts("0");continue;}
		ll ans=ans1+ans2*Time-1LL*(n-id+1)*b;
		printf("%lld\n",ans);
		if(id!=1)update1(1,1,n,1,id-1,Time);
		update2(1,1,n,id,n,b);
		last=d;
	}
}

 


4293: [PA2015]Siano

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 665  Solved: 237
[Submit][Status][Discuss]

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。

 

转载于:https://www.cnblogs.com/wang9897/p/9618063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值