POJ 1195 Mobile phones(二维树状数组,点修改,区间查询)
2015-08-25 11:14
567 查看
题目链接:POJ 1195 Mobile phones
【题目大意】
![](http://img.blog.csdn.net/20150825104709205?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如图所示,开始的操作为 0 初始化 S * S大小的地图,值为0
操作 1, 输入 X Y A, 将地图中坐标为 (X,Y)的值修改为A
操作2, 输入 L B R T 查询 区间 (X,Y) L<=X<=R , B<=Y<=T, 输出该矩形区间的和;
操作 3 结束程序
典型的二维树状数组
二维树状数组和一维树状数组原理是一样的。
我们先回顾一维树状数组 C【maxn】,
它的储存结构
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
……
C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
......
![](http://img.blog.csdn.net/20150825110014218?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
而二维树状数组的第二维 与普通一维树状数组原理是一样的
设二维树状数组为 C[][]
例:举个例子来看看C[][]的组成。
设原始二维数组为:
A[][]={{a11,a12,a13,a14,a15,a16,a17,a18,a19},
{a21,a22,a23,a24,a25,a26,a27,a28,a29},
{a31,a32,a33,a34,a35,a36,a37,a38,a39},
{a41,a42,a43,a44,a45,a46,a47,a48,a49}};
那么它对应的二维树状数组C[][]呢?
B[1]={a11,a11+a12,a13,a11+a12+a13+a14,a15,a15+a16,...} 这是第一行的一维树状数组
B[2]={a21,a21+a22,a23,a21+a22+a23+a24,a25,a25+a26,...} 这是第二行的一维树状数组
B[3]={a31,a31+a32,a33,a31+a32+a33+a34,a35,a35+a36,...} 这是第三行的一维树状数组
B[4]={a41,a41+a42,a43,a41+a42+a43+a44,a45,a45+a46,...} 这是第四行的一维树状数组
那么:
C[1][1]=a11,C[1][2]=a11+a12,C[1][3]=a13,C[1][4]=a11+a12+a13+a14,c[1][5]=a15,C[1][6]=a15+a16,...
这是A[][] 第一行 的一维树状数组
C[2][1]=a11+a21,C[2][2]=a11+a12+a21+a22,C[2][3]=a13+a23,C[2][4]=a11+a12+a13+a14+a21+a22+a23+a24,C[2][5]=a15+a25,C[2][6]=a15+a16+a25+a26,...
这是A[][]数组 第一行与第二行 相加后的树状数组
C[3][1]=a31,C[3][2]=a31+a32,C[3][3]=a33,C[3][4]=a31+a32+a33+a34,C[3][5]=a35,C[3][6]=a35+a36,...
这是A[][] 第三行 的一维树状数组
C[4][1]=a11+a21+a31+a41,C[4][2]=a11+a12+a21+a22+a31+a32+a41+a42,C[4][3]=a13+a23+a33+a43,...
这是A[][]数组 第一行+第二行+第三行+第四行
后的树状数组
注意加粗的部分,可以看出第二维之间储存值的关系和 第一维之间储存值得关系是一样的 ,
储存的项数都是 lowbit(i)。
所以修改和查询的函数,嵌套两个for循环就可以完成了
以上数据来源:
树状数组讲的很好的文章
【源代码】
【题目大意】
如图所示,开始的操作为 0 初始化 S * S大小的地图,值为0
操作 1, 输入 X Y A, 将地图中坐标为 (X,Y)的值修改为A
操作2, 输入 L B R T 查询 区间 (X,Y) L<=X<=R , B<=Y<=T, 输出该矩形区间的和;
操作 3 结束程序
典型的二维树状数组
二维树状数组和一维树状数组原理是一样的。
我们先回顾一维树状数组 C【maxn】,
它的储存结构
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
……
C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
......
而二维树状数组的第二维 与普通一维树状数组原理是一样的
设二维树状数组为 C[][]
例:举个例子来看看C[][]的组成。
设原始二维数组为:
A[][]={{a11,a12,a13,a14,a15,a16,a17,a18,a19},
{a21,a22,a23,a24,a25,a26,a27,a28,a29},
{a31,a32,a33,a34,a35,a36,a37,a38,a39},
{a41,a42,a43,a44,a45,a46,a47,a48,a49}};
那么它对应的二维树状数组C[][]呢?
B[1]={a11,a11+a12,a13,a11+a12+a13+a14,a15,a15+a16,...} 这是第一行的一维树状数组
B[2]={a21,a21+a22,a23,a21+a22+a23+a24,a25,a25+a26,...} 这是第二行的一维树状数组
B[3]={a31,a31+a32,a33,a31+a32+a33+a34,a35,a35+a36,...} 这是第三行的一维树状数组
B[4]={a41,a41+a42,a43,a41+a42+a43+a44,a45,a45+a46,...} 这是第四行的一维树状数组
那么:
C[1][1]=a11,C[1][2]=a11+a12,C[1][3]=a13,C[1][4]=a11+a12+a13+a14,c[1][5]=a15,C[1][6]=a15+a16,...
这是A[][] 第一行 的一维树状数组
C[2][1]=a11+a21,C[2][2]=a11+a12+a21+a22,C[2][3]=a13+a23,C[2][4]=a11+a12+a13+a14+a21+a22+a23+a24,C[2][5]=a15+a25,C[2][6]=a15+a16+a25+a26,...
这是A[][]数组 第一行与第二行 相加后的树状数组
C[3][1]=a31,C[3][2]=a31+a32,C[3][3]=a33,C[3][4]=a31+a32+a33+a34,C[3][5]=a35,C[3][6]=a35+a36,...
这是A[][] 第三行 的一维树状数组
C[4][1]=a11+a21+a31+a41,C[4][2]=a11+a12+a21+a22+a31+a32+a41+a42,C[4][3]=a13+a23+a33+a43,...
这是A[][]数组 第一行+第二行+第三行+第四行
后的树状数组
注意加粗的部分,可以看出第二维之间储存值的关系和 第一维之间储存值得关系是一样的 ,
储存的项数都是 lowbit(i)。
所以修改和查询的函数,嵌套两个for循环就可以完成了
void modify(int a,int b,int val){ for(int i=a;i<=n;i+=lowbit(i)){ for(int j=b;j<=n;j+=lowbit(j)) s[i][j]+=val; } } int sum(int x,int y){ int ans=0; for(int i=x;i>0;i-=lowbit(i)){ for(int j=y;j>0;j-=lowbit(j)) ans+=s[i][j]; } return ans; }
以上数据来源:
树状数组讲的很好的文章
【源代码】
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1111;
int s[maxn][maxn];
int n;
int lowbit(int x){ //求x二进制表示的最后一个1所在位置,,当然返回的值是最后一个1及其后面0所组成的二进制数
return x&(-x);
}
void modify(int a,int b,int val){ for(int i=a;i<=n;i+=lowbit(i)){ for(int j=b;j<=n;j+=lowbit(j)) s[i][j]+=val; } } int sum(int x,int y){ int ans=0; for(int i=x;i>0;i-=lowbit(i)){ for(int j=y;j>0;j-=lowbit(j)) ans+=s[i][j]; } return ans; }
int getsum(int x1,int y1,int x2,int y2){
return sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1); //先求最大区间 ,减去上面多余的,左边多余的, 加上左上角减去两次的。
}
int main(){
int op;
while(scanf("%d%d",&op,&n)!=EOF){
memset(s,0,sizeof(s));
int order;
int a,b,c,d;
while(scanf("%d",&order)!=EOF && order != 3){
if(order==1){
scanf("%d%d%d",&a,&b,&c);
modify(a+1,b+1,c);
}
else {
scanf("%d%d%d%d",&a,&b,&c,&d);
int ans = getsum(a+1,b+1,c+1,d+1);
printf("%d\n",ans);
}
}
}
return 0;
}
相关文章推荐
- Entity Framework - 出現Cannot attach the file錯誤
- 部署XenMobile并与XenDesktop集成 - Citrix Workspace Suite
- ubuntu 14.04开机出现错误“Error found when loading /root/.profile”解决
- Astgo基本操作教程----No.1:中继管理&呼出路由组设置
- Android版:验证手机号码的正则表达式
- leetcode: (190) Reverse Bits
- Java的注解机制——Spring自动装配的实现原理
- iOS-设置视图的边框
- synchronized与static synchronized 的区别
- Warning: Attempt to present UINavigationController on NavigationController which is already presenti
- 如何注册OCX控件
- java I/O流
- 二叉树遍历
- H264基础概念
- Xposed框架原理深入研究
- vimperator 用法
- IOS学习第一篇 ——堆和栈的内存分析
- 双栈排序(Java)
- Jsp 中out.println()为什么不换行
- ZH奶酪:ionic+angularJS+cordova(FileTransfer)上传图片【移动端】