BUPT2017 wintertraining(15) #5A

HDU 4456

题意

给你一个n行n列的格子,一开始每个格子值都是0。有M个操作,p=1为第一种操作,给格子(x,y)增加z。p=2为询问与格子(x,y)的曼哈顿距离不超过z的格子值的和。

(1 ≤ n ≤10 000, 1 ≤ m ≤ 80 000)

题解

这道题如果数据不大,那就可以直接用二维的树状数组来做。

方法1:二维树状数组

因为数据比较大,所以要离线处理并且离散化一下修改的值,再用二维树状数组:

查询的是菱形,我们把坐标用(x-y+n,x+y)来表示,就相当于查询的是矩形了,也就是将坐标轴旋转45°,并平移。

每次修改的坐标(x,y)以(\(x\cdot n\cdot 2+y\))存在h数组中,假设共cnt次修改。给h排个序,再依次处理m个操作。每次修改需要用\(O(log^2(n\cdot 2)\cdot log(cnt))\)的时间,\(pos=lower\_bound(h,h+cnt,i\cdot n\cdot 2+j)-h\),再更新树状数组sum的pos位置的值。每次查询用容斥定理计算一下,树状数组求和过程的i,j位置在h中有对应的值,就把sum[pos]加到ans中。

但是这个h数组和sum数组我觉得开到4000000应该不够的,我认为应该最坏有80000个修改,每个修改\(log^2(n\cdot 2)\)次cnt++,n*2最多是20000,那大概需要80000*15*15=18000000,但是这么大就MLE了,8000000也是MLE。

方法2:cdq分治+树状数组

另外这题和一道经典的cdq分治相似,以下是别人写的题解:

BZOJ 2683 简单题 cdq分治+树状数组 -Claude - 博客频道 - CSDN.NET

只要把方法1中的坐标转换加上就好了。

我自己总结一下就是,将操作按坐标的x为第一关键字,y为第二关键字,操作种类为第三关键字排序。然后将所有操作进行cdq分治。solve(l,r)就是解决时序在l到r的操作,mid=(l+r)/2,时序小于mid的1操作 对 时序大于mid 且 排在它后面的2操作有影响,因此一次循环就可以完成左区间的修改和右区间的累加答案。我们用树状数组sum[i]表示y在[1,i]的格子之和。每次solve时sum都清空一次,也就是只计算x不超过q[mid].x的格子。将时序按不超过mid和超过mid分别放在q的左右两边,再分治处理左右子区间。具体看代码。

代码

方法1

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 80005
#define M 4000000
using namespace std;
int n,m,sum[M];
int p[N],qx[N],qy[N],z[N],h[M],cnt;
void add(int x,int y,int z){
for(;x<=n;x+=x&(-x))
for(int j=y;j<=n;j+=j&(-j))
h[cnt++]=x*n+j;
}
void update(int x,int y,int z){
for(;x<=n;x+=x&(-x))
for(int j=y;j<=n;j+=j&(-j)){
int pos=lower_bound(h, h+cnt, x*n+j)-h;
sum[pos]+=z;
}
}
int getsum(int x,int y){
int ans=0;
for(;x;x-=x&(-x))
for(int j=y;j;j-=j&(-j)){
int pos=lower_bound(h, h+cnt, x*n+j)-h;
if(x*n+j==h[pos])ans+=sum[pos];
}
return ans;
}
int main() {
while(scanf("%d",&n),n){
n*=2;cnt=0;
memset(sum,0,sizeof sum);
scanf("%d",&m);
for(int i=1,x,y;i<=m;i++){
scanf("%d%d%d%d",&p[i],&x,&y,&z[i]);
qx[i]=x-y+n/2,qy[i]=x+y;
if(p[i]==1)add(qx[i],qy[i],z[i]);
}
sort(h,h+cnt);
for(int i=1;i<=m;i++){
if(p[i]==1)update(qx[i],qy[i],z[i]);
else{
int lx=max(1,qx[i]-z[i])-1,rx=min(qx[i]+z[i],n);
int ly=max(1,qy[i]-z[i])-1,ry=min(qy[i]+z[i],n);
printf("%d\n",getsum(rx,ry)-getsum(lx,ry)-getsum(rx,ly)+getsum(lx,ly));
}
}
}
return 0;
}

方法2

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define M 80005
#define N 20005
using namespace std;
struct Query{
int p,x,y,z,i,t;
}q[M<<2],tq[M<<2];
bool cmp(Query a,Query b){
if(a.x==b.x){
if(a.y==b.y)return a.p<b.p;
return a.y<b.y;
}
return a.x<b.x;
}
int sum[N],n2;
void add(int x,int v){
for(;x<=n2;x+=x&(-x))sum[x]+=v;
}
int getsum(int x){
int ans=0;
for(;x;x-=x&(-x))ans+=sum[x];
return ans;
}
int ans[M],cnt;
void solve(int l,int r){
if(l==r)return;
int mid=l+r>>1;
for(int i=l;i<=r;i++)
if(q[i].p==1&&q[i].t<=mid)
add(q[i].y,q[i].z);
else if(q[i].p==2&&q[i].t>mid)
ans[q[i].i]+=q[i].z*getsum(q[i].y);
for(int i=l;i<=r;i++)if(q[i].p==1&&q[i].t<=mid)
add(q[i].y,-q[i].z);
int l1=l-1,l2=mid;
for(int i=l;i<=r;i++)
if(q[i].t<=mid)tq[++l1]=q[i];
else tq[++l2]=q[i];
for(int i=l;i<=r;i++)q[i]=tq[i];
solve(l,mid);solve(mid+1,r);
}
int n,m;
int main() {
while(scanf("%d",&n),n){
scanf("%d",&m);
int t=0;cnt=0;n2=n*2;
memset(ans,0,sizeof ans);
for(int i=1,p,x,y,z;i<=m;i++){
scanf("%d%d%d%d",&p,&x,&y,&z);
if(p==1){
cnt++;
q[cnt]=(Query){p,x+y,x-y+n,z,0,cnt};
}else{
t++;
int xx=x+y,yy=x-y+n;
int x1=max(xx-z-1,1),y1=max(yy-z-1,1);
int x2=min(xx+z,n2),y2=min(yy+z,n2);
cnt++;
q[cnt]=(Query){p,x1,y1,1,t,cnt};
cnt++;
q[cnt]=(Query){p,x2,y2,1,t,cnt};
cnt++;
q[cnt]=(Query){p,x2,y1,-1,t,cnt};
cnt++;
q[cnt]=(Query){p,x1,y2,-1,t,cnt};
}
}
sort(q+1,q+1+cnt,cmp);
solve(1,cnt);
for(int i=1;i<=t;i++)printf("%d\n",ans[i]);
}
return 0;
}

【 HDU - 4456 】Crowd (二维树状数组、cdq分治)的更多相关文章

  1. HDU 4456(二维树状数组+坐标转换)

    题目链接:Problem - 4456 看别人叙述看的心烦,于是我自己画了一张图. 上图. 上代码 #include <iostream> #include <cstdio> ...

  2. hdu 5517 Triple(二维树状数组)

    Triple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. HDU 5517---Triple(二维树状数组)

    题目链接 Problem Description Given the finite multi-set A of n pairs of integers, an another finite mult ...

  4. HDU 5517 【二维树状数组///三维偏序问题】

    题目链接:[http://acm.split.hdu.edu.cn/showproblem.php?pid=5517] 题意:定义multi_set A<a , d>,B<c , d ...

  5. hdu4456 Crowd(二维树状数组)

    题意:给出一个n*n的矩阵,然后m个operation,1表示坐标(x,y)的值加z,2表示与坐标(x,y)的曼哈顿距离不超过z的点的权值和. 解题思路:将矩阵側过来45度.发现询问的时候,有效的点构 ...

  6. HDU 5465 Clarke and puzzle Nim游戏+二维树状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5465 Clarke and puzzle  Accepts: 42  Submissions: 26 ...

  7. hdu 2642 二维树状数组 单点更新区间查询 模板水题

    Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Subm ...

  8. hdu 2642二维树状数组 单点更新区间查询 模板题

    二维树状数组 单点更新区间查询 模板 从零开始借鉴http://www.2cto.com/kf/201307/227488.html #include<stdio.h> #include& ...

  9. HDU_4456_二维树状数组

    http://acm.hdu.edu.cn/showproblem.php?pid=4456 第一道二维树状数组就这么麻烦,题目要计算的是一个菱形范围内的和,于是可以把原来的坐标系旋转45度,就是求一 ...

随机推荐

  1. CF700E Cool Slogans SAM、线段树合并、树形DP

    传送门 在最优的情况下,序列\(s_1,s_2,...,s_k\)中,\(s_i (i \in [2 , k])\)一定会是\(s_{i-1}\)的一个\(border\),即\(s_i\)同时是\( ...

  2. Luogu2993 FJOI2014 最短路径树问题 最短路树、长链剖分

    传送门 强行二合一最为致命 第一问直接最短路+$DFS$解决 考虑第二问,与深度相关,可以考虑长链剖分. 设$f_{i,j}$表示长度为$i$,经过边数为$j$时的最大边权和,考虑到每一次从重儿子转移 ...

  3. 【强化学习】python 实现 q-learning 例三(例一改写)

    本文作者:hhh5460 本文地址:https://www.cnblogs.com/hhh5460/p/10139738.html 例一的代码是函数式编写的,这里用面向对象的方式重新撸了一遍.好处是, ...

  4. WPF没落了吗?

    从08年开始一直到现在,碰到所有的项目,我个人经手的,都用wpf开发. wpf应该说一直没有火过,一直平平淡淡. 个人为什么一直执着用wpf,开始使用是因公司项目,做了两年wpf开发,后来换工作一直搜 ...

  5. [T-ARA][남주긴 아까워][给别人可惜了]

    歌词来源:http://music.163.com/#/song?id=29343992 作曲 : 二段横踢/Radio Galaxi [作曲 : 二段横踢/Radio Galaxi] 作词 : 二段 ...

  6. centos6下ActiveMQ+Zookeeper消息中间件集群部署记录

    由于最近一个项目并发请求压力比较大,所以考虑改进架构,引入消息中间件集群作为一个缓冲消息队列,具体需求:1)将大量的WebService请求报文发送到mq集群之中,并保持消息先后顺序2)保证每个消息的 ...

  7. 个人博客作业Week7(阅读文章,心得体会)

    Alpha阶段结束了,内心可以说是五味杂陈.不是说我们的产品拿不上台面那般差劲,复杂的心绪主要来源于和别的队的比较,别的队才刚刚发布没多久访问量和注册量就破百了,并且还发起了找bug送红包的活动.可能 ...

  8. M2 终审

    1.团队成员简介 左边:马腾跃 右边:陈谋 左上:李剑锋  左下:仉伯龙 右:卢惠明 团队成员及博客: 李剑锋:        Blog:      http://www.cnblogs.com/Po ...

  9. 小学四则运算APP 第一个冲刺阶段 第六天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第一次冲刺阶段时间:11.17~11.27 本次发布的是重新排列整齐ResultActivity的布局代码activity_result. ...

  10. MySQLi面向对象实践--select

    对于update.insert.delete请参考http://www.cnblogs.com/-beyond/p/8457580.html 执行select,如果SQL语句执行成功,那么返回的是一个 ...