AtCoder square869120 Contest #3 F sushi

本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文連接,謝謝合做。node

 

 

 

本文做者:ljh2000
做者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請註明出處,侵權必究,保留最終解釋權!ios

 

題目連接:sushispa

正解:線段樹code

解題報告:blog

  考慮$a[i]>=a[i+1]$恆成立,那麼序列爲一段段相等的數,相似於灌水的問題。get

  那麼用線段樹維護每一個點的權值,不難發現,每次$add$操做,應該是先填平差距,有剩餘的話就總體上升,餘下的部分補給一段前綴。博客

  那麼只須要用線段樹來維護就行了,在線段樹上維護$set$和$add$標記,$pushdown$的時候注意前後順序。string

 

 

//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\n",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;
}
//有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,臥薪嚐膽,三千越甲可吞吳。
相關文章
相關標籤/搜索