VIrtuoso

两把多兰剑加个布甲鞋

导航

Codeforces Round #546 (Div. 2) E 推公式 + 线段树

https://codeforces.com/contest/1136/problem/E

题意

给你一个有n个数字的a数组,一个有n-1个数字的k数组,两种操作:
1.将a[i]+x,假如a[i]+k[i]>a[i+1],则a[i+1]要变成a[i]+k[i],直到某个a[j]+k[j]<=a[j+1]
2.询问某个区间的和

题解

  • 利用题目性质将题目转化到你会的东西的性质

  • \(t_i=k_1+..+k_{i-1},b_i=a_i-t_i\)

    \(a_i \geq a_{i-1} + k_{i-1}\)

    \(a_i - k_{i-1} \geq a_{i-1}\)

    \(a_i - k_{i-1}-...-k_1 \geq a_i - k_{i-2}-...-k_1\)

    \(a_i - t_i \geq a_{i-1} - t_{i-1}\)

    \(b_i \geq b_{i-1}\)

  • 即假如\(b_i\)小于\(b_{i-1}+x\)只需要将\(b_i\)修改成\(b_{i-1}+x\)

  • 二分找到\(b_r\)大于\(b_{i-1}+x\),区间修改

代码

#include<bits/stdc++.h>
#define ll long long 
#define M 100005
#define ls (o<<1)
#define rs (o<<1|1)
#define inf 1e17
using namespace std;
ll a[M],k[M],b[M],t[M],ly[M<<2],X[M<<2],ans;
int n,i,q;
ll x,y,l,r,mid,tp;
char S[3];

void push_up(int o){
	X[o]=X[ls]+X[rs];
}
void push_down(int o,int l,int r){
	int mid=(l+r)/2;
	if(ly[o]!=inf){
		X[ls]=ly[o]*(mid-l+1);
		X[rs]=ly[o]*(r-mid);
		ly[ls]=ly[rs]=ly[o];
		ly[o]=inf;
	}
}
void build(int o,int l,int r){
	int mid=(l+r)/2;
	ly[o]=inf;
	if(l==r){
		X[o]=b[l];return;
	}
	build(ls,l,mid);build(rs,mid+1,r);
	push_up(o);
}
void ud(int o,int l,int r,int L,int R,ll x){
	int mid=(l+r)/2;
	if(L<=l&&r<=R){
		ly[o]=x;X[o]=x*(r-l+1);
		return;
	}
	push_down(o,l,r);
	if(L<=mid)ud(ls,l,mid,L,R,x);
	if(R>mid)ud(rs,mid+1,r,L,R,x);
	push_up(o);
}
ll qy(int o,int l,int r,int L,int R){
	int mid=(l+r)/2;
	if(L<=l&&r<=R){
		return X[o];
	}
	ll ans=0;
	push_down(o,l,r);
	if(L<=mid)ans+=qy(ls,l,mid,L,R);
	if(R>mid)ans+=qy(rs,mid+1,r,L,R);
	return ans;                                 //
}

int main(){
	cin>>n;
	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(i=1;i<n;i++){scanf("%lld",&k[i]);k[i]+=k[i-1];t[i]=t[i-1]+k[i];b[i]=a[i]-k[i-1];}
	b[n]=a[n]-k[n-1];
	build(1,1,n);
	cin>>q;
	while(q--){
		scanf("%s%lld%lld",S,&x,&y);
		if(S[0]=='s'){
			printf("%lld\n",qy(1,1,n,x,y)+t[y-1]-(x>=2?t[x-2]:0));
		}else{
			l=x;r=n;
			tp=qy(1,1,n,x,x)+y;
			while(l<r){
				mid=(l+r)/2;
				if(qy(1,1,n,mid,mid)>=tp)r=mid;
				else {
					l=mid+1;
				}
			}
			if(qy(1,1,n,l,l)>tp)l--;
			//cout<<r<<endl;
			ud(1,1,n,x,l,tp);
		}
	}
}

posted on 2019-03-29 16:15  VIrtuoso  阅读(167)  评论(0编辑  收藏  举报