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 ...
随机推荐
- JQuery Kendo UI使用技巧总结
Kendo UI开发总结 By Gloomyfish on 2013-04-25 在Grid中支持分页刷新: scrollable: {virtual : true }, 在Gr ...
- 使用dom4j对xml文件进行增删改查
1.使用dom4j技术对dom_demo.xml进行增删改查 首选要下载dom4j的jar包 在官网上找不到,网上搜索了一下在这个链接:http://sourceforge.net/projects/ ...
- (转载)myeclipse项目名称重命名
myeclipse项目名称重命名 实例1 今天晚上在做一个jsp唱片显示的实例,myeclipse项目名称原本想写music结果写成了musci.这就需要项目名称的重命名,单纯的使用 “重构--> ...
- oracle学习----访问路径
什么是访问路径?表扫描数据的时候使用了什么方式,这个方式就是访问路径 1.全表扫描TABLE ACCESS FULL 全表扫描,多块读,等待事件:db file scattered read 如果是并 ...
- 佛主保佑,永无bug
/* _ooOoo_ o8888888o 88" . "88 ...
- [转载]SharePoint 网站管理-PowerShell
1. 显示场中所有可用的网站集 Get-SPSite Get-SPSite 2. 显示某一Web应用程序下可用的网站集 Get-SPSite –WebApplication "SharePo ...
- [功能帮助类] C#RandomHelper随机数,随机字符,可限制范围-帮助类 (转载)
点击下载 RandomHelper.rar 主要功能如下 .生成一个指定范围的随机整数,该随机数范围包括最小值,但不包括最大值 .生成一个0.0到1.0的随机小数 .对一个数组进行随机排序 . 一:随 ...
- centos 彻底卸载mysql
yum remove mysql mysql-server mysql-libs compat-mysql51rm -rf /var/lib/mysqlrm /etc/my.cnf查看是否还有mysq ...
- 小白偶遇Sublime Text 3
sublime text3号称神一样的编辑器,主要归功于它丰富的插件所带来的可扩展性.以前曾经抱着玩一玩的心态下载了sublime ,没有插件的sublime 很快被我扔到一边.在用过很多的编辑器后, ...
- iOS崩溃报告获取二
// // JKExceptionHandler.h // JKExceptionHandler // // Created by Jack on 16/9/7. // Copyright © 201 ...