A simple problem with Integers
Time Limit: 5000/1500 MS (Java/others) memory limit: 32768/32768 K (Java/Others)
Total submission (s): 3708 accepted submission (s): 1139
Problem descriptionlet A1, A2 ,..., an be n elements. you need to deal with two kinds of operations. one type of operation is to add a given number to a few numbers in a given interval. the other is to query the value of some element.
Inputthere are a lot of test cases.
The first line contains an integer n. (1 <=n <= 50000)
The second line contains N numbers which are the initial values of A1, A2,..., An. (-10,000,000 <= the initial value of AI <= 10,000,000)
The third line contains an integer Q. (1 <= q <= 50000)
Each of the following Q lines represents an operation.
"1 A B k c" means adding C to each of AI which satisfies a <= I <= B and (I-A) % K = 0. (1 <= A <= B <= N, 1 <= k <= 10,-1,000 <= C <= 1,000)
"2 A" means querying the value of AA. (1 <= A <= N)
Outputfor each test case, output several lines to answer all query operations.
Sample Input
4 1 1 1 1142 12 22 32 41 2 3 1 22 1 2 22 32 41 1 4 2 12 12 22 32 4
Sample output
111113312341
First, let's design the top-level model. See:
Suppose we have inserted three segments: L1 R1 K1 c1l2 R2 K2 c2l3 R3 K3 C3 and then queried the I point in the figure. Then, I just need to traverse all the inserted line segments that contain the I point, and then judge (I-l) % K whether it is = 0, if it is equal to 0, add the initial value of point I to C. Implementation: The brute-force implementation will definitely time out. The timeout lies in finding a line segment containing the I point. We can use the line segment tree to solve the problem of finding a line segment containing the I point. See:
When we look for point 2 in the figure, in fact, each line segment that passes through the line segment tree query 2 contains the point 2. Now the problem is converted to: you only need to judge (I-l) % K = 0 in the current line segment, and then + C. Because 1 <= k <= 10, the range is very small, so each line segment has an array sum [11] to record the information inserted into this segment, for example, if the I of a certain point in the current line segment satisfies (I-l) % K = 0, it can be + C, then sum [k] = C. For example, if we insert: a B k C1 2 2 2 1, then sum [2] = 1 in the [1, 2] line segment. Suppose we query the point 1 now, when [1, 2] is reached, because (1-1) % 2 = 0, the final answer is the initial value + 1. the above example shows how the Inserted Line is directed to the left son, but when the line is directed to the right son, there is a problem. Let's look at the example below. Suppose we insert: a B k C2 4 2 1
We found a problem, that is, when [2, 4] goes to the right subtree, the interval is changed to [3, 4], but the left boundary of [3, 4] is L = 3, (L-) % K = (3-2) % 2! = 0. In this way, an error occurs when we query point 3, because when we query point 3, it goes through [3, 4], (3-3) % 2 = 0 then the answer will be + 1, but (3-2) % 2! = 0. Therefore, we must ensure that the Left endpoint (L-a) % K must be equal to 0 when inserting. Therefore, when going to the right side, we need to slightly process the interval. Generally, we will write: Update (Mid + 1, R, 2 * k + 1); now: int TL = Mid + 1 + (k-(Mid + 1) % K; Update (TL, R, 2 * k + 1); of course TL <= r, otherwise, you do not need to insert it.
#include <iostream>#include <cstdio>using namespace std;const int maxn = 50010;struct tree{ int l , r, k[12];}a[4*maxn];int num[maxn] , N , Q;void build(int l , int r , int k){ a[k].l = l; a[k].r = r; for(int i = 0; i < 12; i++) a[k].k[i] = 0; if(l != r){ int mid = (l+r)/2; build(l , mid , 2*k); build(mid+1 , r , 2*k+1); }}void update(int l , int r , int k , int lk , int lc){ if(l <= a[k].l && a[k].r <= r) a[k].k[lk] += lc; else{ int mid = (a[k].l+a[k].r)/2; if(mid >= r) update(l , r, 2*k , lk , lc); else if(mid < l) update(l , r , 2*k+1 , lk , lc); else{ update(l , mid , 2*k , lk , lc); int tl = mid+1+(lk-(mid+1-l)%lk)%lk; if(tl <= r) update(tl , r , 2*k+1 , lk , lc); } }}int getAns(int k , int i){ int ans = 0; for(int j = 1; j <= 10; j++){ if((i-a[k].l)%j == 0) ans += a[k].k[j]; } return ans;}int query(int l , int r , int k){ if(l <= a[k].l && a[k].r <= r) return getAns(k , l); else{ int mid = (a[k].l+a[k].r)/2; int ans = getAns(k , l); if(mid >= r) return ans+query(l , r , 2*k); else return ans+query(l , r , 2*k+1); }}void computing(){ for(int i = 1; i <= N; i++) scanf("%d" , &num[i]); build(1 , N , 1); scanf("%d" , &Q); int op , la, lb , lk , lc; while(Q--){ scanf("%d" , &op); if(op == 1){ scanf("%d%d%d%d" , &la , &lb , &lk , &lc); update(la , lb , 1 , lk , lc); }else{ scanf("%d" , &la); printf("%d\n" , num[la]+query(la , la , 1)); } }}int main(){ while(~scanf("%d" , &N)){ computing(); } return 0;}
HDU 4267 a simple problem with integers (tree structure-line segment tree)