tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树
P1716 - 上帝造题的七分钟
From Riatre Normal (OI)
总时限:50s 内存限制:128MB 代码长度限制:64KB
背景 Background
裸体就意味着身体。
描述 Description
“第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵。
第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作。
第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
第五分钟,和雪说,要有耐心,于是便有了时间限制。
第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造裸题的七分钟》
所以这个神圣的任务就交给你了。
输入格式 InputFormat
输入数据的第一行为X n m,代表矩阵大小为n×m。
从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:
L a b c d delta —— 代表将(a,b),(c,d)为顶点的矩形区域内的所有数字加上delta。
k a b c d —— 代表求(a,b),(c,d)为顶点的矩形区域内所有数字的和。
请注意,k为小写。
输出格式 OutputFormat
针对每个k操作,在单独的一行输出答案。
样例输入 SampleInput [复制数据]
X 4 4
L 1 1 3 3 2
L 2 2 4 4 1
k 2 2 3 3
样例输出 SampleOutput [复制数据]
12
数据范围和注释 Hint
对于10%的数据,1 ≤ n ≤ 16, 1 ≤ m ≤ 16, 操作不超过200个.
对于60%的数据,1 ≤ n ≤ 512, 1 ≤ m ≤ 512.
对于100%的数据,1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, 1 ≤ delta ≤ 500,操作不超过200000个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。
来源 Source
by XLk
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 2050
#define MAXT 5000000
typedef int tree_t[MAXN][MAXN];
tree_t tree1,tree2,tree3,tree4;
int lowbit(int x)
{
return x&(-x);
}
void add_val(tree_t tree,int x,int y,int v)
{
// cout<<"ADD"<<x<<" "<<y<<" "<<v<<endl;
int i,j;
for (i=x;i<MAXN;i+=lowbit(i))
{
for (j=y;j<MAXN;j+=lowbit(j))
{
tree[i][j]+=v;
}
}
}
int query_sum(tree_t tree,int x,int y)
{
int i,j;
int ret=;
for (i=x;i;i-=lowbit(i))
{
for (j=y;j;j-=lowbit(j))
{
ret+=tree[i][j];
}
}
return ret;
}
//sum(x,y)=segma(a[i][j]*(x-i+1)*(y-j+1))
// =segma(a[i][j]*(x+1)*(y+1)-(i+j)*a[i][j]);
// =segma(a[i][j])*(x+1)*(y+1)-segma((i+j)*a[i][j])
//
void add_matrix(int xl,int yl,int xr,int yr,int v)
{
add_val(tree1,xr+,yr+,v);
add_val(tree1,xl,yl,v);
add_val(tree1,xl,yr+,-v);
add_val(tree1,xr+,yl,-v);
add_val(tree2,xr+,yr+,v*(xr+)*(yr+));
add_val(tree2,xl,yl,v*(xl+)*(yl+));
add_val(tree2,xl,yr+,-v*(xl+)*(yr+));
add_val(tree2,xr+,yl,-v*(yl+)*(xr+)); add_val(tree3,xr+,yr+,v*(xr+));
add_val(tree3,xl,yl,v*(xl+));
add_val(tree3,xl,yr+,-v*(xl+));
add_val(tree3,xr+,yl,-v*(xr+)); add_val(tree4,xr+,yr+,v*(yr+));
add_val(tree4,xl,yl,v*(yl+));
add_val(tree4,xl,yr+,-v*(yr+));
add_val(tree4,xr+,yl,-v*(yl+)); }
int query_matrix(int x,int y)
{
if (!x || !y)return ;
int ret=;
int t;
ret+=query_sum(tree1,x,y)*(x+)*(y+);
ret-=(t=query_sum(tree3,x,y))*(y+);
ret-=query_sum(tree4,x,y)*(x+);
ret+=query_sum(tree2,x,y);
return ret;
}
int main()
{
freopen("input.txt","r",stdin);
int i,j,k;
int n,m;
int x,y,z;
char opt;
scanf("%c%d%d\n",&opt,&n,&m);
int a,b,c,d,e;
while (~scanf("%c",&opt))
{
if (opt=='L')
{
scanf("%d%d%d%d%d\n",&a,&b,&c,&d,&e);
add_matrix(a,b,c,d,e);
}else
{
scanf("%d%d%d%d\n",&a,&b,&c,&d);
printf("%d\n",query_matrix(a-,b-)+query_matrix(c,d)
-query_matrix(a-,d)-query_matrix(c,b-));
}
}
}
树状数组解法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 2050
#define MAXT 2000000
#define midx ((tree[now].lx+tree[now].rx)>>1)
#define midy ((tree[now].ly+tree[now].ry)>>1)
#define tnly tree[now].ly
#define tnry tree[now].ry
#define tnlx tree[now].lx
#define tnrx tree[now].rx
#define tnlazy tree[now].lazy
#define area(t) ((tree[t].rx-tree[t].lx+1)*(tree[t].ry-tree[t].ly+1))
struct node
{
int ch[][];
int lx,rx,ly,ry;
int sum;
int lazy=;
}tree[MAXT];
int root=,topt=;
void new_node(int &now,int lx,int rx,int ly,int ry)
{
if (lx>rx ||ly>ry)return ;
now=++topt;
tnlx=lx;
tnrx=rx;
tnly=ly;
tnry=ry;
} void down(int now)
{
if (!tree[now].ch[][])
new_node(tree[now].ch[][],tnlx,midx,tnly,midy);
if (!tree[now].ch[][] && tnly<tnry)
new_node(tree[now].ch[][],tnlx,midx,midy+,tnry);
if (!tree[now].ch[][] && tnlx<tnrx)
new_node(tree[now].ch[][],midx+,tnrx,tnly,midy);
if (!tree[now].ch[][] && tnly<tnry && tnlx<tnrx)
new_node(tree[now].ch[][],midx+,tnrx,midy+,tnry);
if (tnlazy)
{
tree[tree[now].ch[][]].sum+=tnlazy*area(tree[now].ch[][]);
tree[tree[now].ch[][]].lazy+=tnlazy;
if (tnlx<tnrx)
{
tree[tree[now].ch[][]].sum+=tnlazy*area(tree[now].ch[][]);
tree[tree[now].ch[][]].lazy+=tnlazy;
}
if (tnly<tnry)
{
tree[tree[now].ch[][]].sum+=tnlazy*area(tree[now].ch[][]);
tree[tree[now].ch[][]].lazy+=tnlazy;
}
if (tnlx<tnrx && tnly<tnry)
{
tree[tree[now].ch[][]].sum+=tnlazy*area(tree[now].ch[][]);
tree[tree[now].ch[][]].lazy+=tnlazy;
}
tnlazy=;
}
}
void up(int now)
{
tree[now].sum=;
tree[now].sum+=tree[tree[now].ch[][]].sum;
tree[now].sum+=tree[tree[now].ch[][]].sum;
tree[now].sum+=tree[tree[now].ch[][]].sum;
tree[now].sum+=tree[tree[now].ch[][]].sum;
}
void add_val(int &now,int lx,int rx,int ly,int ry,int v)
{
if (tnlx==lx &&tnly==ly && tnrx==rx &&tnry==ry)
{
tree[now].sum+=v*(rx-lx+)*(ry-ly+);
tree[now].lazy+=v;
return ;
}
down(now);
if (rx<=midx && ry<=midy)
{
add_val(tree[now].ch[][],lx,rx,ly,ry,v);
up(now);
return ;
}
if (rx<=midx && ly> midy)
{
add_val(tree[now].ch[][],lx,rx,ly,ry,v);
up(now);
return ;
}
if (lx> midx && ry<=midy)
{
add_val(tree[now].ch[][],lx,rx,ly,ry,v);
up(now);
return ;
}
if (lx> midx && ly> midy)
{
add_val(tree[now].ch[][],lx,rx,ly,ry,v);
up(now);
return ;
}
if (rx<=midx)
{
add_val(tree[now].ch[][],lx,rx,ly,midy,v);
add_val(tree[now].ch[][],lx,rx,midy+,ry,v);
up(now);
return ;
}
if (lx> midx)
{
add_val(tree[now].ch[][],lx,rx,ly,midy,v);
add_val(tree[now].ch[][],lx,rx,midy+,ry,v);
up(now);
return ;
}
if (ry<=midy)
{
add_val(tree[now].ch[][],lx,midx,ly,ry,v);
add_val(tree[now].ch[][],midx+,rx,ly,ry,v);
up(now);
return ;
}
if (ly> midy)
{
add_val(tree[now].ch[][],lx,midx,ly,ry,v);
add_val(tree[now].ch[][],midx+,rx,ly,ry,v);
up(now);
return ;
}
add_val(tree[now].ch[][],lx,midx,ly,midy,v);
add_val(tree[now].ch[][],lx,midx,midy+,ry,v);
add_val(tree[now].ch[][],midx+,rx,ly,midy,v);
add_val(tree[now].ch[][],midx+,rx,midy+,ry,v);
up(now);
return ;
}
int query(int now,int lx,int rx,int ly,int ry)
{
if (tree[now].lx==lx && tree[now].rx==rx &&
tree[now].ly==ly && tree[now].ry==ry)
{
return tree[now].sum;
}
down(now);
int ans=;
if (rx<=midx && ry<=midy)
{
ans=query(tree[now].ch[][],lx,rx,ly,ry);
return ans;
}
if (rx<=midx && ly> midy)
{
ans=query(tree[now].ch[][],lx,rx,ly,ry);
return ans;
}
if (lx> midx && ry<=midy)
{
ans=query(tree[now].ch[][],lx,rx,ly,ry);
return ans;
}
if (lx> midx && ly> midy)
{
ans=query(tree[now].ch[][],lx,rx,ly,ry);
return ans;
}
if (rx<=midx)
{
ans=query(tree[now].ch[][],lx,rx,ly,midy);
ans+=query(tree[now].ch[][],lx,rx,midy+,ry);
return ans;
}
if (lx> midx)
{
ans=query(tree[now].ch[][],lx,rx,ly,midy);
ans+=query(tree[now].ch[][],lx,rx,midy+,ry);
return ans;
}
if (ry<=midy)
{
ans=query(tree[now].ch[][],lx,midx,ly,ry);
ans+=query(tree[now].ch[][],midx+,rx,ly,ry);
return ans;
}
if (ly> midy)
{
ans=query(tree[now].ch[][],lx,midx,ly,ry);
ans+=query(tree[now].ch[][],midx+,rx,ly,ry);
return ans;
}
ans=query(tree[now].ch[][],lx,midx,ly,midy);
ans+=query(tree[now].ch[][],lx,midx,midy+,ry);
ans+=query(tree[now].ch[][],midx+,rx,ly,midy);
ans+=query(tree[now].ch[][],midx+,rx,midy+,ry);
up(now);
return ans;
}
int main()
{
//freopen("input.txt","r",stdin);
int i,j,k;
int n,m;
int x,y,z;
char opt;
scanf("%c%d%d\n",&opt,&n,&m);
tree[].lx=;tree[].rx=n;
tree[].ly=;tree[].ry=m;
tree[].sum=tree[].lazy=;
topt=;
root=;
int a,b,c,d,e;
while (~scanf("%s",&opt))
{
if (opt=='L')
{
scanf("%d%d%d%d%d\n",&a,&b,&c,&d,&e);
add_val(root,a,c,b,d,e);
}else
{
scanf("%d%d%d%d\n",&a,&b,&c,&d);
printf("%d\n",query(root,a,c,b,d));
}
} }
二维线段书解法
tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树的更多相关文章
- 二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟
详细解释见小结.http://blog.csdn.net/zmx354/article/details/31740985 #include <algorithm> #include < ...
- [luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)
P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a ...
- BZOJ 3132: 上帝造题的七分钟( 二维BIT )
二维树状数组... 自己YY一下再推一下应该可以搞出来... --------------------------------------------------------------------- ...
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...
- BZOJ3132 上帝造题的七分钟 【二维树状数组】
题目 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的 ...
- 二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟
P4514 上帝造题的七分钟 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了00的n×mn×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b)(a,b),右下 ...
- P4514 上帝造题的七分钟(二维树状数组)
P4514 上帝造题的七分钟 二维树状数组 差分维护区间加法,区间求和 #include<cstdio> int read(){ ,f=; ') f=f&&(c!='-') ...
- TYVJ 1941 BZOJ3038 上帝造题的七分钟2 并查集+树状数组
背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段数中每个 ...
- P4514 上帝造题的七分钟——二维树状数组
P4514 上帝造题的七分钟 求的是矩阵里所有数的和: 维护四个树状数组: #include<cstdio> #include<cstring> #include<alg ...
随机推荐
- C语言 小游戏之贪吃蛇
还记得非常久曾经听群里人说做贪吃蛇什么的,那时候大一刚学了C语言,认为非常难,根本没什么思路. 前不久群里有些人又在谈论C语言贪吃蛇的事了,看着他们在做,我也打算做一个出来. 如今大三,经过了这一年半 ...
- Android之PreferenceActivity 详解
看到很多书中都没有对PreferenceActivity做介绍,而我正好又在项目中用到,所以就把自己的使用的在这总结一下,也方便日后查找. PerferenceActivity是什么,看下面的截图: ...
- pcap文件格式
pcap文件格式 pcap文件格式是bpf保存原始数据包的格式,很多软件都在使用,比如tcpdump.wireshark等等,了解pcap格式可以加深对原始数据包的了解,自己也可以手工构造任意的数 ...
- j2ee学习笔记URLEncoder.encode(String , enc)处理特殊字符
从页面上传递数据时,特殊字符对于超链接会自动进行解码 : 其他方式需要手动进行解码.
- oracle设定用户密码使用时间
强制用户定期更换密码,要怎么设置? 假设密码用10天之后必须修改,宽限期为2天: 把电脑时间往后调十天,然后登录: 系统提示用户密码两天内失效,这时把电脑系统再往后调两天,然后登录: 系统提示密码已经 ...
- Java线性表的排序
Java线性表的排序 ——@梁WP 前言:刚才在弄JDBC的时候,忽然觉得order-by用太多了没新鲜感,我的第六感告诉我java有对线性表排序的封装,然后在eclipse里随便按了一下“.” ,哈 ...
- python matplotlib.plot画图显示中文乱码的问题
在matplotlib.plot生成的统计图表中,中文总是无法正常显示.在网上也找了些资料,说是在程序中指定字体文件,不过那样的话需要对plot进行很多设置,而且都是说的设置坐标轴标题为中文,有时候图 ...
- Frequent Pattern 挖掘之二(FP Growth算法)(转)
FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...
- media queries 媒体查询使用
media queries 翻译过来就是媒体查询,media 指的媒体类型.那么有哪些类型呢,常用的有 screen(屏幕).打印(print),个人理解就是它所在的不同终端. 常用的用法:1,< ...
- a标签的简单用法
1.href="#"的作用:页面中有滚动,可以直接回到顶部. <a href="#">回到最顶端</a> 2.href="ur ...