• 2019ICPC徐州 H.Yuuki and a problem


    给一个序列

    要支持两个操作

    1. 修改 (A[x] = y)
    2. 区间询问 ([L,R]) 中最小的不能被表示为 ([L,R]) 中子集合 ((subset)) 的和 正整数

    首先要明白的几件事情是

    首先用一个桶装每个值的和

    • 如果没有 (1) 的话,答案就是 (1)
    • 若现在能凑成 ([1,sum]) ,如果再来一个 (sum+1) ,就可以凑成 ([1,2sum+1])
    • 最开始有 (x)(1) 的话,可以凑成 ([1,x]) ,我们计算 (X = sum_{i=1}^{x+1}sum_i) ,

    若数字 (x) 出现 (k) 次 , 则 (sum_x = kx) 。 若 (X = x) ,则答案就是 (x+1)

    这样迭代,速度很快

    然后数据结构上,用树状数组套一个权值线段树就可以。

    树状数组维护了前缀和信息,可以进行区间内的查询。

    #include<bits/stdc++.h>
    typedef long long ll;
    #define mid (l+r>>1)
    #define min(a,b) (a<b?a:b)
    using namespace std;
    
    const int N = 2e5 + 10;
    
    ll sum[N * 100];int Lc[N * 100], Rc[N * 100], tot;
    
    void insert(int& rt, int l, int r, int val, int pos) {
    	if (!rt)rt = ++tot;
    	sum[rt] += val;
    	if (l == r)return;
    	if (pos <= mid)insert(Lc[rt], l, mid, val, pos);
    	else insert(Rc[rt], mid + 1, r, val, pos);
    }
    
    ll query(int rt, int l, int r, int L, int R) {
    	if (!rt) return 0;
    	if (L <= l and r <= R)return sum[rt];
    	ll ans = 0;
    	if (L <= mid)ans += query(Lc[rt], l, mid, L, R);
    	if (R > mid) ans += query(Rc[rt], mid + 1, r, L, R);
    	return ans;
    }
    
    int lowbit(int x) { return x & (-x); }
    int root[N];
    const int M = N - 1;
    void insert(int pos, int ppos, int val) {
    	for (int i = pos; i <= M; i += lowbit(i)) {
    		insert(root[i], 1, M, val, ppos);
    	}
    }
    ll query(int l, int r, int L, int R) {
    	ll ans = 0;
    	for (int i = r; i; i -= lowbit(i)) {
    		ans += query(root[i], 1, M, L, R);
    	}
    	for (int i = l - 1; i; i -= lowbit(i)) {
    		ans -= query(root[i], 1, M, L, R);
    	}
    	return ans;
    }
    
    int n, q;
    int A[N];
    signed main() {
    	scanf("%d%d", &n, &q);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", A + i);
    		insert(i, A[i], A[i]);
    	}
    	while (q--) {
    		int op, a, b; scanf("%d%d%d", &op, &a, &b);
    		if (op == 1) {
    			insert(a, A[a], -A[a]);
    			A[a] = b;
    			insert(a, A[a], A[a]);
    		}
    		else {
    			ll sum = query(a, b, 1, 1);
    			if (!sum) puts("1");
    			else {
    				ll last = sum;
    				while (1) {
    					sum = query(a, b, 1, min(last + 1, M));
    					if (sum == last)break;
    					last = sum;
    				}
    				printf("%lld
    ", last + 1);
    			}
    		}
    	}
    }
    
  • 相关阅读:
    Atitit.auto complete 自动完成控件的实现总结
    Atitit. .net c# web 跟客户端winform 的ui控件结构比较
    Atitit.实现继承的原理and方法java javascript .net c# php ...
    Atitit.javascript 实现类的方式原理大总结
    Atitit. BigConfirmTips 控件 大数据量提示确认控件的原理and总结O9
    Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结
    c#类库中使用Session
    Oracle和Redhat下载地址
    IIS (HTTP Error 500.21
    浅淡Windows7 32位与64位/x86与x64的区别
  • 原文地址:https://www.cnblogs.com/sduwh/p/13925230.html
Copyright © 2020-2023  润新知