• Codeforces 1180E Serge and Dining Room


    题意
    (n)个菜肴,有(m)个小朋友,每个菜肴的价格为(a_i),每个小朋友有(b_i)元钱,小朋友从(1 ightarrow m)依次购买菜肴,当第(i)个小朋友轮到的时候,他会购买他买的起的最贵的,否则就离开。
    要求支持修改第(i)个菜肴的价格和修改第(i)个小朋友的拥有的钱数的两种操作,每次操作完成给出(m)个小朋友买完后剩下的最贵的菜肴的价格是多少。

    思路
    假设价格大于(x)(y)个菜肴都被买了,那么显然拥有钱数(geq x)的小朋友个数一定要(geq y),显然如何购买是无所谓的。
    那么就在(a_i)处减一,(b_i)处加一,每次询问一个最大的(l)使得([l, infty])的最大后缀和(> 0)
    线段树维护即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 1000010
    #define M 1000000
    int n, m, q, a[N], b[N];
    
    struct SEG {
    	struct node {
    		int sum, Max;
    		node() {
    			sum = Max = 0;
    		}
    		node(int sum, int Max) : sum(sum), Max(Max) {}  
    		node operator + (const node &other) const {
    			node res = node();
    			res.sum = sum + other.sum;
    			res.Max = max(other.Max, Max + other.sum);
    			return res;
    		}
    	}t[N << 2];
    	void init() {
    		memset(t, 0, sizeof t);
    	}
    	void update(int id, int l, int r, int x, int v) {
    		if (l == r) {
    			t[id].sum += v; 
    			t[id].Max += v; 
    			return;
    		}   
    		int mid = (l + r) >> 1;
    		if (x <= mid) update(id << 1, l, mid, x, v);
    		else update(id << 1 | 1, mid + 1, r, x, v);
    		t[id] = t[id << 1] + t[id << 1 | 1];
    	}
    	int query(int id, int l, int r, node tmp) {  
    		if (l == r) {
    			return l;
    		}
    		int mid = (l + r) >> 1; 
    		node tmp2 = t[id << 1 | 1] + tmp; 
    		if (tmp2.Max > 0) {
    			return query(id << 1 | 1, mid + 1, r, tmp);
    		} else {
    			return query(id << 1, l, mid, tmp2);
    		}
    	}
    }seg;
    
    int main() {
    	while (scanf("%d%d", &n, &m) != EOF) {
    		seg.init();
    		for (int i = 1; i <= n; ++i) {
    			scanf("%d", a + i);
    			seg.update(1, 1, M, a[i], 1);
    		}
    		for (int i = 1; i <= m; ++i) {
    			scanf("%d", b + i);
    			seg.update(1, 1, M, b[i], -1);
    		}
    		scanf("%d", &q);
    		int op, x, v;
    		while (q--) {
    			scanf("%d%d%d", &op, &x, &v);  
    			switch(op) {
    				case 1 :
    					seg.update(1, 1, M, a[x], -1);
    					seg.update(1, 1, M, a[x] = v, 1);
    					break; 
    				case 2 :
    					seg.update(1, 1, M, b[x], 1);
    					seg.update(1, 1, M, b[x] = v, -1);
    					break;
    				default :  
    					assert(0);
    			}
    		   	if (seg.t[1].Max <= 0) {
    				puts("-1");
    			} else {
    				printf("%d
    ", seg.query(1, 1, M, SEG::node(0, 0)));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java数据类型
    Hadoop之MapReduce单词计数经典实例
    亲戚问你每月多少工资?程序员该如何机智回答
    MySQL进阶操作
    MySQL基础操作
    Redis安装教程
    希尔排序(Shell Sort)
    插入排序(Insertion Sort)
    javascriptの循序渐进(一)
    css Animation初体验
  • 原文地址:https://www.cnblogs.com/Dup4/p/11090274.html
Copyright © 2020-2023  润新知