1014 迪拜的超市 思维 二分 线段树 清空
链接:https://ac.nowcoder.com/acm/contest/26896/1014
来源:牛客网
题目描述
forever97家住迪拜一环,因此有很多大大小小的商场。
迪拜一环有n个超市,分别在坐标轴[1,n]位置,forever97家在0这个位置。
由于日常开销巨大,所以Trote_w经常让forever97出去买东西。
假如forever97现在要买k件物品,他会从第一家超市开始买东西,买完第一家之后向右走,直到买完k件物品为止。
在开始的时候,每个商店都是0个物品。
有以下两种操作:
1 l r x:代表[l,r]这个区间的超市都购入了x件物品
2 k:代表forever97要买入k个物品(注意:买完之后每个商店的商品会减少被购买的数量)
现在forever97想知道对于每个2操作,他走到哪个商店才能买完k个物品。
迪拜一环有n个超市,分别在坐标轴[1,n]位置,forever97家在0这个位置。
由于日常开销巨大,所以Trote_w经常让forever97出去买东西。
假如forever97现在要买k件物品,他会从第一家超市开始买东西,买完第一家之后向右走,直到买完k件物品为止。
在开始的时候,每个商店都是0个物品。
有以下两种操作:
1 l r x:代表[l,r]这个区间的超市都购入了x件物品
2 k:代表forever97要买入k个物品(注意:买完之后每个商店的商品会减少被购买的数量)
现在forever97想知道对于每个2操作,他走到哪个商店才能买完k个物品。
输入描述:
多组数据9
第一行一个T(1<=T<=10)代表样例组数
对于每组样例
第一行一个n(1<=n<=100000)代表商店个数,一个q(1<=q<=100000)代表操作次数。
接下来q行
每行为上述1操作或者2操作
1<=l<=r<=n 1<=x<=10000
1<=k<=10
输出描述:
对于每个2操作,输出一个数字y,代表forever97走到y商店能买完k件物品。
如果所有超市的物品总和不够k件,那么forever97会放弃这次购买,输出"Trote_w is sb"。
分析
函数写的越多,维护起来越容易
题目要求1~x 区间内从前往后依次取出一些物品直到达到 k
可以用二分,如果当前区间的左边有小于 k 个物品,直接把它们清空并往右找就可以了
如果左边物品数大于 k 那继续往左找
sd 的lazy标记表示这一段要不要清空
//-------------------------代码---------------------------- #define int ll const int N = 1e5+10; int n,m; struct node { int l,r,s,la; bool sd; }tr[N<<2]; void build(int u,int l,int r) { tr[u] = {l,r,0,0}; if(l == r) {;return;} build(ul,l,tr_mid);build(ur,tr_mid+1,r); } void push_down(int u) { if(tr[u].l == tr[u].r) rt; if(tr[u].sd == 1) { tr[ul].la = tr[ul].s = 0; tr[ul].sd = 1; tr[ur].la = tr[ur].s = 0; tr[ur].sd = 1; tr[u].sd = 0; } if(tr[u].la) { tr[ul].la += tr[u].la; tr[ul].s += tr[u].la * tr_len(ul); tr[ur].la += tr[u].la; tr[ur].s += tr[u].la * tr_len(ur); tr[u].la = 0; } } int query(int u,int l,int r) { if(l <= tr[u].l && tr[u].r <= r) return tr[u].s; if(tr[u].l > r || tr[u].r < l) return 0; push_down(u); return query(ul,l,r) + query(ur,l,r); } void mo(int u,int l,int r,int c) { if(l <= tr[u].l && tr[u].r <= r) { tr[u].la += c; tr[u].s += c * tr_len(u); return; } push_down(u); if(l <= tr_mid) mo(ul,l,r,c); if(tr_mid < r) mo(ur,l,r,c); tr[u].s = tr[u<<1].s + tr[ur].s; } #define F cout<<"Trote_w is sb"<<endl; int q; int find(int u,int k) { tr[u].s -= k; if(tr[u].l == tr[u].r) return tr[u].l; push_down(u); if(tr[ul].s < k) { k -= tr[ul].s; tr[ul].s = tr[ul].la = 0; tr[ul].sd = 1; return find(ur,k); } return find(ul,k); } void solve() { // cin>>n>>m; cin>>n>>q; build(1,1,n); while(q -- ) { int op;cin>>op; if(op == 1) { int l,r,x;cin>>l>>r>>x; mo(1,l,r,x); } else { int k;cin>>k; if(tr[1].s<k) {F} else cout<<find(1,k)<<endl; } } } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------