zoukankan      html  css  js  c++  java
  • [CF1439C] Greedy Shopping

    [题目链接]

    https://codeforces.com/contest/1439/problem/C

    [题解]

    首先对于 (1) 操作 , 对一段前缀取 (max) 后 , 整个序列仍然满足单调不增的性质。 在线段树上二分 , 整体赋值即可。

    对于 (2) 操作 , 注意到取走的数必然是不超过 (log(N)) 个连续段。 这是由单调不增的性质得来的。

    那么在线段树上再次二分即可。

    时间复杂度 : (O(NlogN))

    [代码]

    #include <bits/stdc++.h>
     
    using namespace std;
     
    typedef long long LL;
     
    const int MN = 5e5 + 5;
     
    int N , M , A[MN] , tg[MN << 2] , mn[MN << 2];
    LL sum[MN << 2];
     
    inline void pushup(int now) {
    	sum[now] = sum[now << 1] + sum[now << 1 | 1];
    	mn[now] = min(mn[now << 1] , mn[now << 1 | 1]);
    }
    inline void build(int now , int l , int r) {
    	tg[now] = -1;
    	if (l == r) {
    		sum[now] = mn[now] = A[l];
    		return;
    	}
    	int mid = l + r >> 1;
    	build(now << 1 , l , mid) , build(now << 1 | 1 , mid + 1 , r);
    	pushup(now); 
    }
    inline void pushdown(int now , int l , int r) {
    	if (tg[now] == -1) return;
    	int mid = l + r >> 1;
    	mn[now << 1] = mn[now << 1 | 1] = tg[now];
    	sum[now << 1] = 1LL * (mid - l + 1) * tg[now]; sum[now << 1 | 1] = 1LL * (r - mid) * tg[now];
    	tg[now << 1] = tg[now] , tg[now << 1 | 1] = tg[now]; tg[now] = -1;
    	return;
    }
    inline LL query(int now , int l , int r , int ql , int qr) {
    	if (l == ql && r == qr) return sum[now];
    	int mid = l + r >> 1; pushdown(now , l , r);
    	if (mid >= qr) return query(now << 1 , l , mid , ql , qr);
    	else if (mid + 1 <= ql) return query(now << 1 | 1 , mid + 1 , r , ql , qr);
    	else return query(now << 1 , l , mid , ql , mid) + query(now << 1 | 1 , mid + 1 , r , mid + 1 , qr);
    } 
    inline void modify(int now , int l , int r , int ql , int qr , int val) {
    	if (l == ql && r == qr) {
    		mn[now] = val; sum[now] = 1LL * (r - l + 1) * val;
    		tg[now] = val; return;
    	}
    	int mid = l + r >> 1; pushdown(now , l , r);
    	if (mid >= qr) modify(now << 1 , l , mid , ql , qr , val);
    	else if (mid + 1 <= ql) modify(now << 1 | 1 , mid + 1 , r , ql , qr , val);
    	else modify(now << 1 , l , mid , ql , mid , val) , modify(now << 1 | 1 , mid + 1 , r , mid + 1 , qr , val);
    	pushup(now);
    }
    inline int ask(int now , int l , int r , LL &val) {
    	if (val >= sum[now]) {
    		val -= sum[now];
    		return r - l + 1;
    	}
    	if (l == r) return 0;
    	int mid = l + r >> 1; pushdown(now , l , r);
    	int res = 0;
    	if (mn[now << 1] <= val) res += ask(now << 1 , l , mid , val);
    	if (mn[now << 1 | 1] <= val) res += ask(now << 1 | 1 , mid + 1 , r , val);
    	return res;
    }
     
    int main() {
    	
    	scanf("%d%d" , &N , &M);
    	for (int i = 1; i <= N; ++i) scanf("%d" , &A[i]);
    	build(1 , 1 , N);
    	for (int i = 1; i <= M; ++i) {
    		int op , x; LL y;
    		scanf("%d%d%lld" , &op , &x , &y);
    		if (op == 1) {
    			int l = 1 , r = x , ans = 0;
    			while (l <= r) {
    				int mid = l + r >> 1;
    				if (query(1 , 1 , N , mid , mid) < y) {
    					ans = mid;
    					r = mid - 1;
    				} else l = mid + 1;
    			}
    			if (ans) modify(1 , 1 , N , ans , x , y);
    		} else {
    			if (x > 1) y += query(1, 1, N, 1, x - 1);
    			printf("%d
    " , ask(1 , 1 , N , y) - (x - 1));
    		}
    	}	
    	return 0;
    }
  • 相关阅读:
    给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组以及删除了重复条目的原数组。
    mysql批量替换某个字段的值!
    LInux常用命令
    盒模型布局
    box-sizing -- 盒模型
    vue中使用svg字体图标
    字体图标
    在线字体
    Java QQ邮箱发送邮件
    Java 对全局用户是否登录验证
  • 原文地址:https://www.cnblogs.com/evenbao/p/14039431.html
Copyright © 2011-2022 走看看