Train of Thought: when I saw this question during the competition, I felt like a line segment tree or a tree array, but I was overwhelmed because I had to double the interval, after thinking for a long time, I don't know how to deal with the double number. Then I keep thinking about the first question. Although I have done this kind of tree array before, it is really wise to use the tree array.
Sum [I] is the prefix of the tree array, and CNT [I] indicates the total number of I numbers.
Update doubling process: When we double the range (L, R), find the number corresponding to L in the binary tree array, find the number corresponding to R, and update the numbers by single point, why do we need to update these two numbers at a single point? For example, for the sequence 1 1 1 2 2 3 3 3 4 4 4, so (L, R) = (), the number of 1 is found at 2, but it starts from the first position, so it only contains two 1 s; the 8 position also contains only two 3 s, not all 1 s and 3 s, this is why the endpoint location should be updated separately. Then update the number between them in the interval. For example, in the above sequence, the number between update 1 and 3 is the number of all 2, that is, the total number of three must be doubled.
The same is true for search.
# Pragma comment (linker, "/Stack: 1024000000,1024000000 ") # include <iostream> # include <cstdio> # include <cstring> # include <algorithm> # include <map> # include <queue> # include <set> # include <cmath> # include <bitset> # define MEM (, b) memset (a, B, sizeof (A) # define lson I <1, L, mid # define rson I <1 | 1, Mid + 1, R # define llson j <1, L, mid # define rrson j <1 | 1, Mid + 1, R # define INF 0x7fffffff # define maxn 50005 typedef long ll; typedef unsigned long ull; using namespace STD; ll sum [maxn], CNT [maxn]; int n, m; ll getsum (int x) {ll ans = 0; for (INT I = x; I> 0; I-= I & (-I) ans + = sum [I]; return ans;} void add (INT X, ll v) {for (INT I = x; I <= N; I + = I & (-I) sum [I] + = V ;} int find (LL v) {int L = 1, R = N, mid; while (L <r) {mid = (L + r)> 1; if (getsum (MID)> = V) r = mid; else l = Mid + 1;} return r;} void Update (ll l, ll R) {int L = find (L), r = find (r); If (L = r) {Add (L, R-l + 1 ); CNT [l] + = r-L + 1; return;} ll LL = getsum (L), RR = getsum (R-1); add (L, ll-L + 1), add (R, R-rr); // separately update CNT [l] + = ll-L + 1, CNT [R] + = r-RR; For (INT I = L + 1; I <r; I ++) add (I, CNT [I]), CNT [I] + = CNT [I];} ll query (ll l, ll R) {int L = find (L), r = find (R ); if (L = r) return r-L + 1; ll max = 0; max = getsum (l)-L + 1; max = max (max, r-getsum (R-1); For (INT I = L + 1; I <r; I ++) max = max (max, CNT [I]); return Max;} int main () {// freopen ("1.txt"," r ", stdin); int T, II = 1; char s [3]; scanf ("% d", & T); While (t --) {scanf ("% d", & N, & M); For (INT I = 0; I <= N; I ++) sum [I] = 0; For (INT I = 1; I <= N; I ++) add (I, 1 ), CNT [I] = 1; printf ("case # % d: \ n", II ++); ll l, R; while (M --) {scanf ("% S % i64d % i64d", S, & L, & R); If (s [0] = 'D') Update (L, R ); else printf ("% i64d \ n", query (L, R) ;}} return 0 ;}
Tenth multi-school event: HDU 4973 tree array + prefix + binary