A Simple Problem with Integers
Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4283 Accepted Submission(s): 1334
Problem Description
Let 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.
Input
There 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)
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)
Output
For each test case, output several lines to answer all query operations.
Sample Input
4
1 1 1 1
14
2 1
2 2
2 3
2 4
1 2 3 1 2
2 1
2 2
2 3
2 4
1 1 4 2 1
2 1
2 2
2 3
2 4
Sample Output
1
1
1
1
1
3
3
1
2
3
4
1
Source
树状数组,更新区间,查询单点,区别是加了一个a%k==0的条件限制....
我们观察到k很小,于是按照k分类....
每一类再按照余数分类,一共55棵树(1+2+3+...+10)
然后写完交上去,竟然MLE了。。。
13×13*50007
我一开始也想到了是开大了。。。然后改成了11*11*50004,结果还是mle..
然后我就把代码贴到群里问了。。。。
然后就被打脸了。。。
被这顿嘲讽啊。。。
由于我的vim不知道什么原因,要复制两次才能复制上去。。。
就是说,改成了11*11*50004的代码并没有提交上去,第二次mle还是13*13*50007。。
不过也算一个经验:对于低维度(一维)数组,稍微开大点对空间影响不会很大...
但是高维,稍微开大一点,就会极大的影响空间....因为是乘起来的。
因为之前很少遇到高维,而且数组比较大的情况,所以没有太注意。
也说明把数组开大一点就好,一点点。
代码是按照hdu 4267 写的
poj 3468和这个差不多,就是读入顺序和op的写法不太一样。
另:某博客看到的tips,虽然我也知道这个,但我觉得他表达得比较清楚...
Tips:
树状数组的优势是方便动态求值和更新..
可惜树状数组是单点更新
倒是有个方法可以快速成段更新
就是在区间【a, b】内更新+x就在a的位置+x 然后在b+1的位置-x
求某点a的值就是求数组中1~a的和..
可惜这道题还不是成段更新..而是隔开几个数来更新..
所以就可以多建几棵树..然后就可以转换为成段更新了~~
其中每个位置初始值用一个数组保存..在每次询问的时候加上就好..
/****....********************************************************************* > File Name: code/hdu/4267.cpp > Author: 111qqz > Email: rkz2013@126.com > Created Time: 2015年08月07日 星期五 14时27分58秒 ************************************************************************/ #include<iostream> #include<iomanip> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<map> #include<set> #include<queue> #include<vector> #include<stack> #define y0 abc111qqz #define y1 hust111qqz #define yn hez111qqz #define j1 cute111qqz #define tm crazy111qqz #define lr dying111qqz using namespace std; #define REP(i, n) for (int i=0;i<int(n);++i) typedef long long LL; typedef unsigned long long ULL; const int inf = 0x7fffffff; const int N=5E4+3; int c[N][11][11]; int a[N]; int n,m,k,del,x,q,y; bool flag; int lowbit( int x) { return x&(-x); } void update ( int a,int b,int x, int delta) { for ( int i = x; i <= n ; i = i + lowbit (i)) { c[i][a][b] += delta; } } int sum ( int a,int b,int x) { int res = 0; for ( int i = x; i >= 1; i = i - lowbit (i)) { res = res + c[i][a][b]; } return res; } int main() { while (scanf("%d",&n)!=EOF) { memset(c,0,sizeof(c)); flag = true; for ( int i = 1 ;i <= n ; i++ ) { scanf("%d",&a[i]); } scanf("%d",&q); flag = false; int op; for ( int i = 1 ; i <= q ; i ++) { scanf("%d",&op); if (op==1) { scanf("%d %d %d %d",&x,&y,&k,&del); update (k,x%k,x,del); update(k,x%k,y+1,-del); } else { scanf("%d",&x); int ans = a[x]; for ( int i = 1 ; i <= 10 ; i++) { ans = ans +sum(i,x%i,x); } cout<<ans<<endl; } } } return 0; }