• AtCoder square869120 Contest #3 F sushi


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:sushi

    正解:线段树

    解题报告:

      考虑$a[i]>=a[i+1]$恒成立,那么序列为一段段相等的数,类似于灌水的问题。

      那么用线段树维护每个点的权值,不难发现,每次$add$操作,应该是先填平差距,有剩余的话就整体上升,余下的部分补给一段前缀。

      那么只需要用线段树来维护就好了,在线段树上维护$set$和$add$标记,$pushdown$的时候注意先后顺序。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #define lc root<<1
    #define rc root<<1|1
    using namespace std;
    typedef long long LL;
    const int MAXN = 200011;
    int n,Q;
    struct node{ LL set,add,sum; }a[MAXN*3];
    inline void update(int root){ a[root].sum=a[lc].sum+a[rc].sum; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void pushdown(int root,int l,int r){
    	if(a[root].set==0 && a[root].add==0) return  ; if(l==r) return ;
    	int mid=(l+r)>>1;
    	if(a[root].set>0) {
    		a[lc].set=a[rc].set=a[root].set;
    		a[lc].sum=1LL*a[root].set*(mid-l+1); a[rc].sum=1LL*a[root].set*(r-mid);
    		a[lc].add=a[rc].add=a[root].set=0;
    	}
    
    	if(a[root].add>0) {
    		a[lc].add+=a[root].add; a[rc].add+=a[root].add;
    		a[lc].sum+=1LL*a[root].add*(mid-l+1); a[rc].sum+=1LL*a[root].add*(r-mid);
    		a[root].add=0;
    	}
    }
    
    inline void modify(int root,int l,int r,int ql,int qr,LL val){
    	pushdown(root,l,r);
    	if(ql<=l && r<=qr) {
    		a[root].set=val; a[root].add=0;
    		a[root].sum=1LL*(r-l+1)*val;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid) modify(lc,l,mid,ql,qr,val);
    	if(qr>mid) modify(rc,mid+1,r,ql,qr,val);
    	update(root);
    }
    
    inline void add(int root,int l,int r,int ql,int qr,LL val){
    	pushdown(root,l,r);
    	if(ql<=l && r<=qr) {
    		a[root].sum+=1LL*val*(r-l+1);
    		a[root].add+=val;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid) add(lc,l,mid,ql,qr,val);
    	if(qr>mid) add(rc,mid+1,r,ql,qr,val);
    	update(root);
    }
    
    inline LL query(int root,int l,int r,int ql,int qr){
    	if(ql<=l && r<=qr) return a[root].sum;
    	pushdown(root,l,r); int mid=(l+r)>>1;
    	if(qr<=mid) return query(lc,l,mid,ql,qr);
    	else if(ql>mid) return query(rc,mid+1,r,ql,qr);
    	return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
    }
    
    inline void dfs(int root,int l,int r){
    	if(l==r) { printf("%lld
    ",a[root].sum); return ; }
    	pushdown(root,l,r); int mid=(l+r)>>1;
    	dfs(lc,l,mid); dfs(rc,mid+1,r);
    }
    
    inline void work(){
    	n=getint(); Q=getint(); int x; LL y; int l,r,mid,pos;
    	while(Q--) {
    		x=getint(); scanf("%lld",&y);
    		if(x==1) { add(1,1,n,1,1,y); continue; }
    		l=1; r=x; pos=0;
    		while(l<=r) {
    			mid=(l+r)>>1;
    			if(1LL*query(1,1,n,mid,mid)*(x-mid+1)-query(1,1,n,mid,x) <= y) r=mid-1;
    			else l=mid+1,pos=mid;
    		}
    		y-=1LL*query(1,1,n,pos+1,pos+1)*(x-pos)-query(1,1,n,pos+1,x);
    		modify(1,1,n,pos+1,x, query(1,1,n,pos+1,pos+1) );
    		if(y/(x-pos)) add(1,1,n,pos+1,x,y/(x-pos));
    		if(y%(x-pos)) add(1,1,n,pos+1,pos+y%(x-pos),1);
    	}
    	dfs(1,1,n);
    }
    
    int main()
    {
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    react系列(二)高阶组件-HOC
    【译】2分钟介绍Rx
    react系列(一)JSX语法、组件概念、生命周期介绍
    react系列(零)安装
    函数节流和函数防抖
    观察者模式和发布订阅模式(下)
    观察者模式和发布订阅模式(上)
    java学习第二天 20207/7
    2020/7/6博客日报Java的开始--pthread的安装
    node.js实现excel导出/exceljs实现导出
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6869178.html
Copyright © 2020-2023  润新知