[藍橋杯][演算法提高VIP]分蘋果 線段樹

一葉之修發表於2019-03-06

藍橋杯歷年真題題目及題解目錄彙總

 

題目描述

小朋友排成一排,老師給他們分蘋果。 
小朋友從左到右標號1..N。有M個老師,每次第i個老師會給第Li個到第Ri個,一共Ri-Li+1個小朋友每人發Ci個蘋果。 
最後老師想知道每個小朋友有多少蘋果。 

資料規模和約定 
100%的資料,N、M≤100  000,1≤Li≤Ri≤N,0≤Ci≤100。 
 

輸入

第一行兩個整數N、M,表示小朋友個數和老師個數。 
接下來M行,每行三個整數Li、Ri、Ci,意義如題目表述。

輸出

一行N個數,第i個數表示第i個小朋友手上的水果。 

樣例輸入

5  3 
1  2  1 
2  3  2 
2  5  3 

樣例輸出

1  6  5  3  3 

線段樹,這裡的sum感覺就是懶惰標記,到最後統計的時候再往下遞增

import java.util.ArrayList;
import java.util.Scanner;

public class 藍橋杯_分蘋果 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		tree = new SegTree[4*n+5];
		for(int i=0;i<4*n+5;i++) 
			tree[i] = new SegTree();
		buildtree(1,1,n);
		for(int i=0;i<m;i++)
			updata(1, 1, n, in.nextInt(), in.nextInt(), in.nextInt());
		print(1);
		for(int i=0;i<list.size();i++)
			if(i==list.size()-1)
				System.out.println(list.get(i));
			else
				System.out.print(list.get(i)+" ");
	}
	
	static SegTree[] tree;
	static ArrayList<Integer> list = new ArrayList<>();
	
	static class SegTree{
		int l,r,sum;
		public SegTree(int l,int r) {
			this.l = l;
			this.r = r;
		}
		public SegTree() {}
	}
	
	
	static void updata(int now,int l,int r,int x,int y,int d) {
		if(r<x || y<l)
			return;
		if(x<=l && y>=r) {
			tree[now].sum += d;
			return;
		}
		int mid = l + (r-l)/2;
		updata(2*now, l, mid, x, y, d);
		updata(2*now+1, mid+1, r, x, y, d);
	}
	
	static void print(int now) {
		if(tree[now].l==tree[now].r) {
			list.add(tree[now].sum);
			return;
		}
		tree[2*now].sum += tree[now].sum;
		print(2*now);
		tree[2*now+1].sum += tree[now].sum;
		print(2*now+1);
	}
	
	
	
	static void buildtree(int now,int l,int r) {
		tree[now].l = l;
		tree[now].r = r;
		tree[now].sum = 0;
		if(l==r) {
			tree[now].sum = 0;
			return;
		}
		int mid = l + (r-l)/2;
		buildtree(2*now,l,mid);
		buildtree(2*now+1,mid+1,r);
		tree[now].sum = tree[2*now].sum + tree[2*now+1].sum;
	}
	
	

}

 

 

 

 

相關文章