hdu 4267/poj 3468 A Simple Problem with Integers (分状态的树状数组)

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)

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

2012 ACM/ICPC Asia Regional Changchun Online

树状数组,更新区间,查询单点,区别是加了一个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: [email protected]
    > 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;
}
时间: 2024-10-11 15:27:01

hdu 4267/poj 3468 A Simple Problem with Integers (分状态的树状数组)的相关文章

HDU 4267 A Simple Problem with Integers 多个树状数组

A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4000    Accepted Submission(s): 1243 Problem Description Let A1, A2, ... , AN be N elements. You need to deal with

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

POJ 3468 A Simple Problem with Integers 【树状数组】

题目链接:http://poj.org/problem?id=3468 题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c. 完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时. 换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对. 假设数组sum[i]为原数组从v[1]到v[i]的和,数

POJ 3468 A Simple Problem with Integers(详细题解)

这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传. 这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询. Inc往下带的过程也是区

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

线段树(成段更新) POJ 3468 A Simple Problem with Integers

题目传送门 1 /* 2 线段树-成段更新:裸题,成段增减,区间求和 3 注意:开long long:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 using namespace std; 11 12 #define lson l, mid, rt <<

POJ - 3468 A Simple Problem with Integers (区间求和)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In