Hdu4737A Bit Fun line segment tree
// Give a series and ask how many pairs [I, j] Make // [I, j] the value of the sum of all numbers in the interval is smaller than m // you can know the plus (a | B) of the 'or' operation> = max (a, B) // You can enumerate the right r of the range, find the first unsatisfied position on the left // then the r in the middle of them is not satisfied with the boundary range // For the first unsatisfied position, you can use a line segment tree, # include
# Include
# Include
Using namespace std; const int maxn = 100010; # define left v <1 # define right v <1 | 1 struct node {int l, r; int value ;} tree [maxn <2]; int h [maxn]; int m, n; void build (int l, int r, int v) {tree [v]. l = l; tree [v]. r = r; if (l = r) {tree [v]. value = h [l]; return;} int mid = (l + r)> 1; build (l, mid, left); build (mid + 1, r, right); tree [v]. value = tree [left]. value | tree [right]. value;} int get_ans (int v, int sum) {if (tree [v]. l = tree [v]. r) return tree [v]. l; int mid = (tree [v]. l + tree [v]. r)> 1; if (sum | tree [right]. value)> = m) return get_ans (right, sum); else return get_ans (left, sum | tree [right]. value);} int ans = 0; int query (int v, int pos) {if (tree [v]. l = tree [v]. r) return tree [v]. value; int mid = (tree [v]. l + tree [v]. r)> 1; int sum; if (pos <= mid) query (left, pos); else {sum = query (right, pos ); if (sum <m & (sum | tree [left]. value)> = m) {ans = get_ans (left, sum);} return sum | tree [left]. value ;}} int main () {// freopen(in.txt, r, stdin); int T; scanf (% d, & T); int cas = 0; while (T --) {scanf (% d, & n, & m); for (int I = 1; I <= n; I ++) scanf (% d, & h [I]); build (1, n, 1); int sum = 0; for (int I = 1; I <= n; I ++) {ans = 0; if (h [I]> = m) {continue;} query (1, I); sum + = (I-ans);} query (1, 9); printf (Case # % d:, ++ cas); printf (% d, sum );}}