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 ...
随机推荐
- Android中利用OpenMax 编程的基本流程
近期因为公司在做数字电视,播放器和模块由供应商打包一起卖,驱动调通了,但是播放器要硬件解码,和平台差异,原厂又没有相关文档,就自己试着看了一个系统的播放器流程,顺便整理了一下,也方便以后查询,希望对播 ...
- UIImage载入图片的几种方式及差别
用UIImage载入图像的方法非常多.最经常使用的是几种: 1.使用imageNamed函数载入: <span style="font-size:14px;">[UI ...
- UDP 校检和和算法
#include <Winsock2.h> #include <stdio.h> #define IP_HDRINCL 2 // Header is included with ...
- Linux下git的配置
需求和环境 硬件:一台装有Ubuntu14.04的PC 软件:git-core.openssh-server.openssh-client Git的安装 sudo apt-get install gi ...
- thinkphp 常见问题
0.写在最前面的不断更新 (1)trace不起作用 A:必须要输出到模板,才会有trace信息 (2)提示“您浏览的页面暂时发生了错误!请稍后再试-” A:检查控制器(看看能进到控制器没有,设断点输出 ...
- android开发:点击缩略图查看大图
android中点击缩略图查看大图的方法一般有两种,一种是想新浪微博list页面那样,弹出一个窗口显示大图(原activity为背景).另一种就是直接打开一个新的activity显示大图. 1.第一种 ...
- js--小结⑤
js中的for循环,while循环,do...while循环和C语言的一模一样 有几个问题要提醒一下的是 1. null是对象,即object undefined是undefined d ...
- php 计算一个字符串在另一个字符串中出现的次数
<?php $text = 'This is a test'; echo strlen($text); // 14 echo substr_count($text, 'is'); // 2 // ...
- javascript moveTo() 函数
moveTo-- 移动窗体左上角到相对于屏幕左上角的(x,y)点,当使用负数做为参数时会吧窗体移出屏幕的可视区域 moveTo,中文"移动到"的意思 引用网址:http://www ...
- SQL Prompt Snippet Manager 妙用
SQL Prompt有一个很好用的工具叫Snippet Manager,SQL脚本片段管理器. 使用它可以快速的键入一段脚本,如输入ii+Tab,即可变成INSERT INTO 同理,我们可以定义一些 ...