2018ICPC 南京赛区网络赛 G

Question link:https://nanti.jisuanke.com/t/30996

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 blog link of segment tree : https://blog.csdn.net/weixin_40532377/article/details/82784855

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;
 } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值