zoukankan      html  css  js  c++  java
  • 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
    ",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);
    		}
    	}
    }
    
  • 相关阅读:
    图解JAVA对象的创建过程
    统计机器学习
    排序算法简介及其C实现
    linux中强大的screen命令
    C语言注释
    Hello hadoop——使用hadoop进行大规模数据的全局排序
    Hadoop Streaming框架使用(二)
    shell——tr的用法
    统计学习方法《文本分类(三)》
    hadoop 常存问题
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10622042.html
Copyright © 2011-2022 走看看