1. 程式人生 > >2018ICPC 南京賽區網路賽 G

2018ICPC 南京賽區網路賽 G

The translation of question:(please reference Google translation)

Question meaning:balalbala一大頓之後主幹意思就是,有n個房子,裡面有著不用的白熾燈,為了省電,要把這些

白熾燈換成節能燈,每個月給你m個節能燈,然後你從頭開始找,找到需要換的數量小於你手裡節能燈的數量就把

這個房間的燈全給換掉,直到走完全部房間,或者你手裡沒有燈為止,然後等下個月再來m個燈。(月數m<1e5,剛開始

以為只有12個月。。。)然後問你某個月完成了幾個房間,手裡剩下多少幾個燈。

The solution of the question : Segment Tree ,creat a table(打表是這麼寫?)

A few days ago,I have written an article of segment tree.Now it can come in handy.

FIrst of all ,we recall that article together .

The sement tree is the key that you can accepted this question,if you don't know what's segment tree,you kan

view my blog of it, otherwise this quetion will make you confused.

I will explain this question with my code in detail

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int INF=maxn;
struct node{
	int l;
	int r;
	int min;
}room[maxn*4];	//建樹具體見上一個blog 
int n,m;
struct s{
	int save;		//這個月剩下的燈泡 
	int already;	//這個月完成的房間數 
}month[maxn];
void build(int l,int r,int k){
	room[k].l=l;
	room[k].r=r;
	if(l==r) return ;
	
	int mid=(l+r)/2;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
}
void update(int i,int k,int val){
	if(room[k].l==i&&room[k].r==i){
		room[k].min=val;
		return ;
	}
	
	int mid=(room[k].l+room[k].r)/2;
	if(i<=mid) update(i,k*2,val);
	else update(i,k*2+1,val);
	
	room[k].min=min(room[k*2].min,room[k*2+1].min);
}
void search(int k,int i){		//這個地方就要自己好好想想怎麼實現了 
	if(month[i].save<room[k].min) return;	//如果房間的燈泡沒有比手裡少的 直接return 
	
	if(room[k].l==room[k].r){				//找到了某個可以換燈泡的房間 
		month[i].already++;					 
		month[i].save-=room[k].min;
		room[k].min=INF;					//將換完的數目改成INF	 
		return;
	}
	
	search(k*2,i);
	search(k*2+1,i);		
	
	room[k].min=min(room[k*2].min,room[k*2+1].min);		//更新每一層的最小值 
	
}
int main()
{
	int temp;
	memset(month,0,sizeof(month));
	month[0].save=month[0].already=month[1].save=month[1].already=0;
	cin>>n>>m;
	build(1,n,1);
	for(int i=1;i<=n;i++){
		scanf("%d",&temp);
		update(i,1,temp);
	}
	int i;
	for(i=1;i<maxn;i++){
		month[i].already=month[i-1].already;		//每個月剛開始和上個月完成的房間相同 
		if(month[i-1].already<n){
			month[i].save=month[i-1].save+m;		//每個月給你m個燈泡 
			search(1,i);
		}
		else break;
	}
	for(;i<maxn;i++){
		month[i].save=month[i-1].save;
		month[i].already=month[i-1].already;		//全安完了把剩下的表打上 
	}
	int t,q;
	cin>>t;
	while(t--){
		scanf("%d",&q);
		printf("%d %d\n",month[q].already,month[q].save);
	}
	return 0;
 }