571 字
3 分钟
BZOJ 4299 Codechef FRBSUM
Description
数集S的ForbiddenSum定义为无法用S的某个子集(可以为空)的和表示的最小的非负整数。 例如,S={1,1,3,7},则它的子集和中包含0(S’=∅),1(S’={1}),2(S’={1,1}),3(S’={3}),4(S’={1,3}),5(S’ = {1, 1, 3}),但是它无法得到6。因此S的ForbiddenSum为6。 给定一个序列A,你的任务是回答该数列的一些子区间所形成的数集的ForbiddenSum是多少。
Input
输入数据的第一行包含一个整数N,表示序列的长度。 接下来一行包含N个数,表示给定的序列A(从1标号)。 接下来一行包含一个整数M,表示询问的组数。 接下来M行,每行一对整数,表示一组询问。
Output
对于每组询问,输出一行表示对应的答案。
Sample Input
5
1 2 4 9 10
5
1 1
1 2
1 3
1 4
1 5
Sample Output
2
4
8
8
8
HINT
对于100%的数据,1≤N,M≤100000,1≤A_i≤10^9,1≤A_1+A_2+…+A_N≤10^9。
题解
可以看出
如果一个区间能组出1~n的数而且有一个数小于等于n+1
则这个区间一定能构造出 n+1
然后就可以了
用主席树维护一下就可以了
复习一下主席树
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 1e9;struct Seg_Node{ int l, r; Seg_Node *ch[2]; int Sum;} * root[100005], *null;int a[100005];Seg_Node *NewSeg_Node(){ Seg_Node *S = new Seg_Node(); S->ch[0] = S->ch[1] = null; return S;}void copy(Seg_Node *&a, Seg_Node *b){ if (b == null) a = null; else a = NewSeg_Node(), *a = *b;}void Update(int v, int l, int r, Seg_Node *&rt1, Seg_Node *rt2){ copy(rt1, rt2); if(rt1==null) rt1=NewSeg_Node(); rt1->Sum += v; rt1->l = l, rt1->r = r; if (l == r) return; int m = l + r >> 1; if (v <= m) { Update(v, l, m, rt1->ch[0], rt2->ch[0]); } else { Update(v, m + 1, r, rt1->ch[1], rt2->ch[1]); }}int Query(int R, int l, int r, Seg_Node *rt1, Seg_Node *rt2){ if (R >= r) return rt1->Sum - rt2->Sum; int m = l + r >> 1; if (R <= m) return Query(R, l, m, rt1->ch[0], rt2->ch[0]); return Query(R, l, m, rt1->ch[0], rt2->ch[0]) + Query(R, m + 1, r, rt1->ch[1], rt2->ch[1]);}int main(){ null = new Seg_Node(); null->ch[0] = null->ch[1] = null; root[0] = null; int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n; i++) { Update(a[i], 1, 1e9, root[i], root[i - 1]); } int m; scanf("%d", &m); int a, b, ans; while (m--) { scanf("%d%d", &a, &b); int res = 1; ans = min(INF, Query(res, 1, 1e9, root[b], root[a - 1])); while (ans >= res && res < 1e9) { res = ans + 1; ans = min(INF, Query(res, 1, 1e9, root[b], root[a - 1])); } printf("%d\n", ans + 1); }}
BZOJ 4299 Codechef FRBSUM
https://www.nekomio.com/posts/83/