二维树状数组

本文介绍了一个关于二维坐标中矩形内点数量查询的问题,输入包括多个测试案例和查询请求,输出为每个矩形内的点数。文章提供了一段C++代码实现,利用前缀和思想进行高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不用++的话一直超时,也不知道为什么~没找出问题

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

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

Sample Output

Case 1:

2

0

2

3


#include<iostream>
#include<stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
int qq[1031][1031];
bool walked[1031][1031];
int n;
int lowbit(int x){return x&(-x);}
void add(int x,int y){
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=n;j+=lowbit(j))
        qq[i][j]+=1;
}
long long sum(int x,int y){
    long long s=0;
    for(int i=x;i>0;i-=lowbit(i))
        for(int j=y;j>0;j-=lowbit(j))
        s+=qq[i][j];
    return s;
}
int main(){
    freopen("in.txt","r",stdin);
    n=1131;
    int T,f1,f2,f3,f4,i,j,k,t1,t2,t3,m,tt;
    cin >>T;
    long long maxn;
    tt=T;
    while(T--){
            memset(walked,0,sizeof(walked));
        memset(qq,0,sizeof(qq));
            printf("Case %d:\n",tt-T);
        scanf("%d",&m);
        while(m--){
            scanf("%d",&t1);
            if(t1==0){
                scanf("%d%d",&f1,&f2);
                if(!walked[f1][f2]){
                    walked[f1][f2]=1;
			f1++;f2++;
                    add(f1,f2);
                }
            }else{
            scanf("%d%d%d%d",&f1,&f2,&f3,&f4);
            maxn=0;
	f1++;f2++;f3++;f4++;
            maxn=sum(f3,f4)+sum(f1-1,f2-1)-sum(f1-1,f4)-sum(f3,f2-1);
            printf("%d\n",maxn);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值