POJ1195Mobile phones (从二维树状数组到cdq分治)
Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area.
Input
The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3.
Table size: 1 * 1 <= S * S <= 1024 * 1024
Cell value V at any time: 0 <= V <= 32767
Update amount: -32768 <= A <= 32767
No of instructions in input: 3 <= U <= 60002
Maximum number of phones in the whole table: M= 2^30
Output
Sample Input
0 4
1 1 2 3
2 0 0 2 2
1 1 1 2
1 1 2 -1
2 1 1 2 3
3
Sample Output
3
4
题目:二维平面上单点加值操作,矩形区间求和操作。
显然这个数据可以用二维树状数组秒
//poj1195树状数组
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
int sum[maxn][maxn],N;
int lowbit(int x) { return x&(-x); }
void add(int x,int y,int val)
{
for(int i=x;i<=N;i+=lowbit(i))
for(int j=y;j<=N;j+=lowbit(j))
sum[i][j]+=val;
}
int query(int x,int y)
{
int res=;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
res+=sum[i][j];
return res;
}
int main()
{
int opt,a,b,x,y,val;
while(~scanf("%d",&opt)){
scanf("%d",&N);
memset(sum,,sizeof(sum));
while(scanf("%d",&opt)){
if(opt==) break;
if(opt==){
scanf("%d%d%d",&x,&y,&val);
add(x+,y+,val);
}
else{
scanf("%d%d%d%d",&x,&y,&a,&b);
printf("%d\n",query(a+,b+)+query(x,y)-query(a+,y)-query(x,b+));
}
}
} return ;
}
但如果操作不变,二维平面变大,空间不够时,cdq分治就来了。
首先看下面之前,先回顾一下上面的题,二维树状树组可以做,复杂度为(nlg2n),只是空间变大后不行。此题引用cdq分治是为了降二维树状数组为一维。(避免读者误以为cdq分治优化的是复杂度,其实复杂度没有降低。)
nmphy自诉:
1,为了描述,这里假设分治[l,r]部分时,处理[l,mid]的增加对[mid+1,r]的影响叫做“合并”过程。
2,以下的l,mid,r均是指第几个操作,即按时间排序后是第几个操作,而不是x坐标或者y坐标,不要搞混淆。
我们假设有q个操作(即按时间排序),现在在解决[l,r]这几个操作。
可以肯定:当前合并过程中[mid+,r]的增加的值全部来自于[l,mid]。
为什么呢?l之前增加的值对[mid+1,r]的影响呢呢?[mid+,R]内部操作增加的值对内部后面的影响呢?
仔细一看,l之前增加的值在更大的分治里面(即[l,r]属于[L,R],假设[L,R]=[L,mid]+[l,r],那么l之前的[L,mid]部分就在这里合并处理);
而[mid+,r]增加的值在更新的分治里(即[mid+,(mid++r)/],[(mid++r)/+,r])。
从而保证了前面的增加对后面的询问都被考虑到。
但是[l,mid]对[mid+,r]处理时,增加值使用了一次;合并后[l,r]对[r+,r]处理时,显然[l,mid]的增加值又使用了一次。
所以在处理完内部后,还得减去增加值。
上面有点乱的话自己来问我,我觉得理解上面这段话还是很重要的!
所谓cdq分治,就是分治所有操作,计算[l,mid]中的修改对[mid+,r]中的询问的影响。
无法理解的同学可以借助归并排序的思想思考。
抄袭别人讲以上的话吧
、T(n)=2T(n/)+O(kn)的解是T(n)=O(kn log n)
、T(n)=2T(n/)+O(kn log n)的解是T(n)=O(kn log^ n)
、T(n)=2T(n/)+O(k)的解是T(n)=O(kn)
所以cdq分治的复杂度也可以简单的算出来了。
cdq能处理的题目必须满足:、允许离线 、前面的修改对后面的影响很容易算出来 比如说这一题
在[l,mid]部分的修改按x排序从小到大加进一个树状数组里,不断更新对[mid+,r]的影响。
复杂度就是第二种计算方式,可就是O(q log^ w)
因为我们从下向上扫描,所以不需要记录y轴方向的树状数组,只需要跟新x方向即可。
CDQ分治中,首先按x来排序,对t这个维度进行分治。
那么t<=mid的更新操作都能影响到t'>=mid+1的查询结果。
所以在CDQ(l,r)中,按照x从小到大扫一遍所有操作,遇到更新操作就在树状数组上插入y值(y值离散过),
遇到查询操作就给该操作的结果加上树状数组上查询到的sum(,y)的值。
接下来用类似归并排序的方法,把t<=mid的操作都放到数组左半部分,t>=mid+1的操作都放到右半部分
这么做之后两半部分的y依然是有序的,就可以递归处理两半部分之间的更新操作对查询操作产生的影响了。
你瞅啥?
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
const int Maxn=;
int x1[Maxn],x2[Maxn],y1[Maxn],y2[Maxn],tr[Maxn];
int a[Maxn],b[Maxn],c[Maxn],opt[Maxn],ans[Maxn];
int n,m,s,w,i;
struct arr{
int x,l,r,k,c;
bool operator <(const arr &a) const { return x<a.x; }
}qk[Maxn];
struct ad{
int x,y,w;
bool operator <(const ad &a) const { return x<a.x; }
}g[Maxn];
int query(int x){
int ret=;
for (int i=x;i>;i-=lowbit(i)) ret+=tr[i];
return ret;
}
void add(int x,int s){
for(int i=x;i<=m;i+=lowbit(i)) tr[i]+=s;
}
void combine(int l,int r)
{
int mid=(l+r)>>,t=,tt=,i,j;
for(i=mid+;i<=r;i++)
if(opt[i]==){
qk[++t]=(arr){x1[i]-, y1[i], y2[i], i, };
qk[++t]=(arr){x2[i], y1[i], y2[i], i, };
}
sort(qk+,qk+t+); //按x排序
for(i=l;i<=mid;i++)
if(opt[i]==) g[++tt]=(ad){x1[i],y1[i],x2[i]};
sort(g+,g+tt+);
for(i=,j=;i<=tt;i++){
while(j<=t&&qk[j].x<g[i].x){
if (qk[j].c==) ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-);
else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-);
j++;
} add(g[i].y,g[i].w);
}
while(j<=t){
if(qk[j].c==) ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-);
else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-);
j++;
}
for(i=;i<=tt;i++) add(g[i].y,-g[i].w);//减去增加值
}
void cdq(int l,int r){
if(l==r) return;
int mid=(l+r)>>;
cdq(l,mid);
combine(l,r); //前+前半截对后半截的影响+后
cdq(mid+,r);
}
int main(){
scanf("%d%d",&s,&w); n=; //s是初始值,此题为0
while (true){
scanf("%d",&opt[n]);
if(opt[n]==||opt[n]==) break;
if(opt[n]==){
scanf("%d%d%d",&x1[n],&y1[n],&x2[n]);
c[++m]=y1[n];
}else
if(opt[n]==){
scanf("%d%d%d%d",&x1[n],&y1[n],&x2[n],&y2[n]);
ans[n]+=s*(x2[n]-x1[n]+)*(y2[n]-y1[n]+);
c[++m]=y1[n]; c[++m]=y2[n]; //c是复制y坐标来离散
} n++;
}
sort(c+,c+m+); //按y排序
m=unique(c+,c+m+)-(c+); //离散
for(i=;i<n;i++){
y1[i]=lower_bound(c+,c+m+,y1[i])-c;
if(opt[i]==) y2[i]=lower_bound(c+,c+m+,y2[i])-c;
} cdq(,--n);
for(i=;i<=n;i++) if(opt[i]==) printf("%d\n",ans[i]);
return ;
}
园丁的烦恼 SHOI2007 BZOJ 1935
【模板】树状数组 1 luogu P3374
Mokia BZOJ 1176
陌上花开 BZOJ 3262
简单题BZOJ 2683
动态逆序对 CQOI2011 BZOJ 3295
POJ1195Mobile phones (从二维树状数组到cdq分治)的更多相关文章
- 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)
BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...
- poj 1195:Mobile phones(二维树状数组,矩阵求和)
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 14489 Accepted: 6735 De ...
- (简单) POJ 1195 Mobile phones,二维树状数组。
Description Suppose that the fourth generation mobile phone base stations in the Tampere area operat ...
- POJ 1195 Mobile phones (二维树状数组)
Description Suppose that the fourth generation mobile phone base stations in the Tampere area operat ...
- POJ 1195 Mobile phones【二维树状数组】
<题目链接> 题目大意: 一个由数字构成的大矩阵,开始是全0,能进行两种操作1) 对矩阵里的某个数加上一个整数(可正可负)2) 查询某个子矩阵里所有数字的和要求对每次查询,输出结果 解题分 ...
- POJ-2155:Matrix(二维树状数祖)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 31892 Accepted: 11594 Descript ...
- POJ_1195 Mobile phones 【二维树状数组】
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013912596/article/details/33802561 题目链接:id=1195&qu ...
- POJ 1195 Mobile phones(二维树状数组)
Mobile phones Time Limit: 5000MS Mem ...
- POJ 1195 Mobile phones (二维树状数组或线段树)
偶然发现这题还没A掉............速速解决了............. 树状数组和线段树比较下,线段树是在是太冗余了,以后能用树状数组还是尽量用......... #include < ...
随机推荐
- 集团管控的历史读本——Leo鉴书76
当下中国管理咨询界比較火的课题之中的一个就是"集团管控".公司大了之后怎样正好的用人.怎样对下属分公司不失控制.怎样在二代接手之后系统仍然稳固.种种问题都在困扰着企业们.假设我们把 ...
- D类功放基础简介
DAC和D类PA的开关时序是先开dac再开D类pa,先关D类pa再关dac
- 最短路 uva12661 Funny Car Racing
传送门:点击打开链接 题意:给你有向图,每条边呈周期性开放,即开放a时间,再关闭b时间.再开放a时间以此类推 假设时间不足以穿过这条路则不能走.你能够在节点等待时间,问从s走到t所须要的最小时间 细致 ...
- iOS程序自动检测更新的实现
本文转载至 http://blog.csdn.net/davidsph/article/details/8931718 App Store自动更新itunes 之前项目需要用到app自动更 ...
- 前后端分离之fiddler前端开发代理 autoresponder 正则表达式 regex:(?insx) 修正符详解
regex:(?isx)^http://127.0.0.1:3000(/dlscene)?/order/(\w*) http://127.0.0.1:8080/dlscene/order/$2 上面这 ...
- sql中decode()重要函数使用
decode()函数简介: 主要作用:将查询结果翻译成其他值(即以其他形式表现出来,以下举例说明): 使用方法: Select decode(columnname,值1,翻译值1,值2,翻译值2,.. ...
- 一些重要的地址:md5在线解密破解
md5在线解密破解:https://www.cmd5.com/
- Makefile注意点总结
1 "="和":=" "="号赋值时,如果右边的值里面有未展开的变量,要等到整个Makefile的变量处理完之后,再展开,也就是说,如果该未 ...
- CrystalReport runtime的下载地址
SAP网站的东西实在太多了,找个CrytalReport都费劲.13.*版的可以通过下面的地址下载: SAP Crystal Reports, developer version for Micros ...
- Mac环境,React native错误解决方案
运行react-native run-android,报错如下图: 运行react-native run-ios正常,但 react-native run-android时,提示错误: 在网上 ...