LightOJ 1112 Curious Robin Hood && LightOJ 1266 Points in Rectangle(树状数组)

来源:互联网 发布:织梦404页面自动跳转 编辑:程序博客网 时间:2024/05/17 00:19

这两个题是一维树状数组跟二维树状数组的模板题,只不过要改变下原始值,或者根据单个值进行一些操作,这时候只需要建一个数组记录原来的值变化就可以,如果改变这个值了,就把原来的值改变。只需要改变一个值所以复杂度很低。。

如果模板还不是很熟可以看下这个博客:http://blog.csdn.net/qq_34374664/article/details/52787481


1266 - Points in Rectangle
   PDF (English)StatisticsForum
Time Limit: 2 second(s)Memory Limit: 32 MB

As the name says, this problem is about finding the number of points in a rectangle whose sides are parallel to axis. All the points and rectangles consist of 2D Cartesian co-ordinates. A point that lies in the boundary of a rectangle is considered inside.

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing an integer q (1 ≤ q ≤ 30000) denoting the number of queries. Each query is either one of the following:

1)      0 x y, meaning that you have got a new point whose co-ordinate is (x, y). But the restriction is that, if a point (x, y) is already listed, then this query has no effect.

2)      1 x1 y1 x2 y2 meaning that you are given a rectangle whose lower left co-ordinate is (x1, y1) and upper-right corner is (x2, y2); your task is to find the number of points, given so far, that lie inside this rectangle. You can assume that (x1 < x2, y1 < y2).

You can assume that the values of the co-ordinates lie between 0 and 1000 (inclusive).

Output

For each case, print the case number in a line first. Then for each query type (2), you have to answer the number of points that lie inside that rectangle. Print each of the results in separated lines.

Sample Input

Output for Sample Input

1

9

0 1 1

0 2 6

1 1 1 6 6

1 2 2 5 5

0 5 5

1 0 0 6 5

0 3 3

0 2 6

1 2 1 10 10

Case 1:

2

0

2

3

Note

Dataset is huge, use faster I/O methods.


PROBLEM SETTER: JANE ALAM JAN

题意:一个二维平面,两个操作,一个在某个坐标上+一个点,一个求一个矩阵里有几个点,注意,如果第一个操作那个坐标已经有点了,这个操作就作废;

思路:二维树状数组单点更新,区间查询。。纯模板。。。只不过怎样判断这个点有没有点可能会卡住,队友CillyB想的是查询x,y区间都是1的sum。。也就是查这个点上的值是不是1,但是x,y小于1000,直接开一个矩阵就行,如果这个点更新了 把矩阵里的这个值赋值为1,下次如果这个值是1直接pass掉就行,如果x,y,但是如果x,y 都在1e7往上就会爆内存了。。这时候不知道怎么办了,不能离散化把。。。给点离散化,就没办法求矩阵里的点了。。。求大佬指教

代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int maxn = 1e3 + 5;int c[maxn][maxn], matrix[maxn][maxn];int lowbit(int k){    return k & (-k);}void update(int x,int y, int v){    while(x < maxn)    {        int y1 = y;        while(y1 < maxn)        {            c[x][y1] += v;            y1 += lowbit(y1);        }        x += lowbit(x);    }}int sum(int x, int y){    int sum = 0;    while(x > 0)    {        int y1 = y;        while(y1 > 0)        {            sum += c[x][y1];            y1 -= lowbit(y1);        }        x -= lowbit(x);    }    return sum;}int main(){    int t, q, Case = 0;    scanf("%d", &t);    while(t--)    {        printf("Case %d:\n", ++Case);        memset(c, 0, sizeof(c));        memset(matrix, 0, sizeof(matrix));        scanf("%d", &q);        int x, y, x1, y1, x2, y2, cmd;        while(q--)        {            scanf("%d", &cmd);            if(cmd == 0)            {                scanf("%d%d", &x, &y);                x++;y++;                if(!matrix[x][y])                update(x,y,1), matrix[x][y] = 1;            }            if(cmd == 1)            {                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);                x1++;x2++;y1++;y2++;                printf("%d\n", sum(x2,y2)+sum(x1-1,y1-1)-sum(x1-1,y2)-sum(x2,y1-1)); //这里区间更新要注意下,可能会有会的            }        }    }    return 0;}


1112 - Curious Robin Hood
   PDF (English)StatisticsForum
Time Limit: 1 second(s)Memory Limit: 64 MB

Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick. He keeps nsacks where he keeps this money. The sacks are numbered from 0 to n-1.

Now each time he can he can do one of the three tasks.

1)                  Give all the money of the ith sack to the poor, leaving the sack empty.

2)                  Add new amount (given in input) in the ith sack.

3)                  Find the total amount of money from ith sack to jth sack.

Since he is not a programmer, he seeks your help.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case contains two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). The next line contains n space separated integers in the range [0, 1000]. The ithinteger denotes the initial amount of money in the ith sack (0 ≤ i < n).

Each of the next q lines contains a task in one of the following form:

1 i        Give all the money of the ith (0 ≤ i < n) sack to the poor.

2 i v     Add money v (1 ≤ v ≤ 1000) to the ith (0 ≤ i < n) sack.

3 i j      Find the total amount of money from ith sack to jth sack (0 ≤ i ≤ j < n).

Output

For each test case, print the case number first. If the query type is 1, then print the amount of money given to the poor. If the query type is 3, print the total amount from ith to jth sack.

Sample Input

Output for Sample Input

1

5 6

3 2 1 4 5

1 4

2 3 4

3 0 3

1 2

3 0 4

1 1

Case 1:

5

14

1

13

2

Notes

Dataset is huge, use faster I/O methods.


题意:一个数组,三种操作,一个把某个元素变成0,一个把某个元素+上一个数,一个求某个区间的和

思路:模板题,变成0就减去他现在的值就行。还是用一个a数组记录每个元素初始值,注意更新后,不要忘记对初始值a[i]更新

代码:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1e5 + 5;int c[maxn], a[maxn];int lowbit(int k){    return k & (-k);}void update(int n, int v){    while(n < maxn)    {        c[n] += v;        n += lowbit(n);    }}long long sum(int x){    long long sum = 0;    while(x >= 1)    {        sum += c[x];        x -= lowbit(x);    }    return sum;}int  main(){   // freopen("out.txt", "w", stdout);    int Case = 0, t, n, m, x;    scanf("%d", &t);    while(t--)    {        memset(c, 0, sizeof(c));        printf("Case %d:\n", ++Case);        scanf("%d%d", &n, &m);        for(int i = 1; i <= n; i++)            scanf("%d", &a[i]), update(i, a[i]);        int cmd, i, j;        while(m--)        {            scanf("%d", &cmd);            if(cmd == 1)            {                scanf("%d", &i);                update(i+1, -a[i+1]);                printf("%d\n",a[i+1]);                a[i+1] = 0;  //变成0也要更新            }            if(cmd == 2)            {                scanf("%d%d", &i, &j);                update(i+1, j);                a[i+1] += j;            }            if(cmd == 3)            {                scanf("%d%d", &i, &j);                printf("%lld\n", sum(j+1)-sum(i));            }        }    }    return 0;}




1 0