ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps (线段树:无序数组找到第一个小于val)
题意:n个房间,每个房间有ai盏旧灯,每个月可以买m盏新灯,要求:按房间顺序换灯,如果剩下的新灯数目大于ai,那么进行更换,否则跳过该房间,判断下一个房间。如果所有房间都换完灯,那么久不会再买新灯。
q次询问,每次询问该月已换的房间数以及剩余的新灯数量。
题解:线段树记录最小值,然后一遍模拟
#include<bits/stdc++.h> using namespace std ; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define INF 0x3f3f3f3f typedef long long ll; const int maxn = 1e5+5; int n,m; int lamp[maxn << 2]; int q; int month[maxn]; int re; int MIN[maxn << 2]; int ans1[maxn], ans2[maxn]; void pushup(int rt) { MIN[rt] = min(MIN[rt<<1],MIN[rt<<1|1]); } void build(int l , int r , int rt) { if(l == r) { scanf("%d",&MIN[rt]); return ; } int mid = (l+r) >> 1 ; build(lson); build(rson); pushup(rt); } int query(int l , int r , int rt , int val) { if(l==r) { re-=MIN[rt]; MIN[rt]=INF; return 1;///找到了 } int mid = (l + r) >> 1; int pos = 0 ; if(MIN[rt<<1] <= val) ///在左子树找到 { pos = query(lson,val) ; pushup(rt); return pos; } if(MIN[rt<<1|1]<=val)///在右子树找到 { pos = query(rson,val); pushup(rt); return pos; } return 0; } int main ( ) { int n,m; scanf("%d%d",&n,&m); build(1,n,1); int Maxmonth = 0; scanf("%d",&q); for(int i=1 ; i<=q ; i++) { scanf("%d",&month[i]); Maxmonth=max(month[i],Maxmonth); } int cur=1; int cnt=0;///换了多少 int fa=0;///是否换完 while(cur<=Maxmonth) { if(!fa) re+=m; while(query(1,n,1,re)&&!fa) cnt++; if(!fa) { ans1[cur]=cnt; ans2[cur]=re; } else { ans1[cur]=n; ans2[cur]=re; } cur++; if(cnt>=n) fa=1; } for(int i=1 ; i<=q ; i++) printf("%d %d\n",ans1[month[i]],ans2[month[i]]); }