BZOJ 1935 Tree 园丁的烦恼 CDQ分治/主席树
CDQ分治版本
我们把询问拆成四个前缀和,也就是二维前缀和的表达式,
我们把所有操作放入一个序列中
操作1代表在x,y出现一个树
操作2代表加上在x,y内部树的个数
操作3代表减去在x,y内部树的个数
我们对X进行归并排序,并用CDQ计算机左区间对右区间的影响
由于CDQ分治的特性,我们已经求得了[L,MID]之间答案 以及 [MID+1,R]之间答案
那么[L,MID] 对[MID+1,R] 的影响是什么呢?
很简单,对于L<=i<=MID , MID+1<=j<=R 来说
i 对 j 影响是当 a[i]的操作是1,那么会对 j 内的求和操作产生影响。
但是i的求和操作实际上已经进行了不会对j内产生影响,并且j内部的操作1,对j的求和操作也没有影响,而且这一部分实际上是已经计算过的了。
因为我们在计算两个区间的相互影响的时候,就是维护左区间的操作1,以及右区间的求和操作(操作2,操作3)。
#include<bits/stdc++.h>
using namespace std;
const int maxx = ;
const int maxn =;
struct node{
int x,y,op,id;
}a[maxx*],b[maxx*];
int num[maxx];
int sum[maxn];
int mx,tot;
int lowbit(int x){
return x&(-x);
}
void add(int x,int w){
for (int i=x;i<=mx;i+=lowbit(i)){
sum[i]+=w;
}
}
int query(int x){
int ans=;
for (int i=x;i;i-=lowbit(i)){
ans+=sum[i];
}
return ans;
}
void clear_bit(int x){
for (int i=x;i<=mx;i+=lowbit(i)){
if(sum[i]==)break;
sum[i]=;
}
}
void cdq(int l,int r){
if (l==r){
return;
}
int mid=(l+r)>>;
cdq(l,mid);
cdq(mid+,r);
int i=l,j=mid+,k=l;
///归并排序
while(i<=mid && j<=r){
if (a[i].x<=a[j].x){
///如果当前左边的值小于右边,那么对于操作2,3来说,实际上已经是计算过了,并且这个区间对右边区间只有操作1有影响
if(a[i].op==){
add(a[i].y,);
}
///把a[i]加入b[i]中排序
b[k++]=a[i++];
}else {
///如果是操作2的话,我们只需要查询比a[j].y小的个数即可
if(a[j].op==){
num[a[j].id]+=query(a[j].y);
}else if(a[j].op==){
///操作3的话,我们需要减去比a[j].y,
num[a[j].id]-=query(a[j].y);
}
b[k++]=a[j++];
}
}
while(i<=mid){
if(a[i].op==)add(a[i].y,);
b[k++]=a[i++];
}
while(j<=r){
if(a[j].op==)num[a[j].id]+=query(a[j].y);
else if(a[j].op==)num[a[j].id]-=query(a[j].y);
b[k++]=a[j++];
}
for (int i=l;i<=r;i++){
clear_bit(a[i].y);
a[i]=b[i];
}
}
int main(){
int n,m,lx,ly,rx,ry;
scanf("%d%d",&n,&m);
tot=;
mx=;
int x,y;
memset(num,,sizeof(num));
///左标+1防止树状数组取到0
for (int i=;i<=n;i++){
scanf("%d%d",&x,&y);
x++;
y++;
tot++;
a[tot].x=x;
a[tot].y=y;
a[tot].op=;
}
for(int i=;i<=m;i++){
scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
lx++;ly++;rx++;ry++;
///二维前缀和
a[++tot]={lx-,ly-,,i};
a[++tot]={rx,ry,,i};
a[++tot]={lx-,ry,,i};
a[++tot]={rx,ly-,,i};
mx=max(mx,ly);
mx=max(mx,ry);
}
cdq(,tot);
for (int i=;i<=m;i++){
printf("%d\n",num[i]);
}
return ;
}
当然这道题也是可以用主席树写的。。。嘿嘿
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int maxx = 5e5+;
struct node{
int l,r;
LL w;
}tree[maxx*];
int root[maxx];
struct Node{
int x,y;
LL w;
bool operator < (const Node & s)const{
return x<s.x;
}
}point[maxx];
vector<int>vx;
vector<int>vy;
LL n;
int cnt;
LL get_val(LL x,LL y){
LL k=min(x,min(n-x+,min(y,n-y+)));
LL minn=k;
k--;
LL in=n-*k;
LL out=n*n-in*in;
if (x==n-minn+){
return out+n-k-y+;
}else if (y==minn){
return out+in+n-k-x;
}else if (x==minn){
return out+in*-+y-k;
}else {
return out+in*-+x-k;
}
}
void inserts(int l,int r,int pre,int &now,int pos,LL w){
now=++cnt;
tree[now]=tree[pre];
tree[now].w+=w;
if(l==r){
return ;
}
int mid=(l+r)>>;
if(pos<=mid)inserts(l,mid,tree[pre].l,tree[now].l,pos,w);
else inserts(mid+,r,tree[pre].r,tree[now].r,pos,w);
}
LL query(int L,int R,int l,int r,int ql,int qr){
//区间查询
if(ql<=l && r<=qr){
return tree[R].w-tree[L].w;
}
int mid=(l+r)>>;
LL ans=;
if (qr<=mid){
return query(tree[L].l,tree[R].l,l,mid,ql,qr);
}else if (ql>mid){
return query(tree[L].r,tree[R].r,mid+,r,ql,qr);
}else {
return query(tree[L].l,tree[R].l,l,mid,ql,qr)+query(tree[L].r,tree[R].r,mid+,r,ql,qr);
}
}
int main(){
int m,p;
cnt=;
memset(root,,sizeof(root));
memset(tree,,sizeof(tree));
scanf("%d%d",&m,&p);
vx.clear();
vy.clear();
for(int i=;i<=m;i++){
scanf("%d%d",&point[i].x,&point[i].y);
point[i].w=;
vx.push_back(point[i].x);
vy.push_back(point[i].y);
}
sort(point+,point++m);
sort(vx.begin(),vx.end());
sort(vy.begin(),vy.end());
vy.erase(unique(vy.begin(),vy.end()),vy.end());
int sz=vy.size();
for (int i=;i<=m;i++){
int posy=lower_bound(vy.begin(),vy.end(),point[i].y)-vy.begin()+;
inserts(,sz,root[i-],root[i],posy,point[i].w);
}
while(p--){
int lx,rx,ly,ry;
scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
lx=lower_bound(vx.begin(),vx.end(),lx)-vx.begin()+;
rx=upper_bound(vx.begin(),vx.end(),rx)-vx.begin();
ly=lower_bound(vy.begin(),vy.end(),ly)-vy.begin()+;
ry=upper_bound(vy.begin(),vy.end(),ry)-vy.begin();
if (lx>rx || ly>ry){
printf("0\n");
continue;
}
printf("%lld\n",query(root[lx-],root[rx],,sz,ly,ry));
}
return ;
}
/* */
BZOJ 1935 Tree 园丁的烦恼 CDQ分治/主席树的更多相关文章
- BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 +CDQ分治
1935: [Shoi2007]Tree 园丁的烦恼 参考与学习:https://www.cnblogs.com/mlystdcall/p/6219421.html 题意 在一个二维平面中有n颗树,有 ...
- BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)
题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 43 ...
- BZOJ1935:[SHOI2007]Tree 园丁的烦恼(CDQ分治)
Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: ...
- BZOJ 1935 Tree 园丁的烦恼 (树状数组)
题意:中文题. 析:按x排序,然后用树状数组维护 y 即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000" ...
- bzoj 1935 Tree 园丁的烦恼
题目大意: 一些点,每次查询一个矩形内有多少个点 思路: 因为空间太大 所以不能用什么二维树状数组 需要把这些点和所有查询的矩阵的左下和右上离线下来 先离散化 然后每个子矩阵像二维前缀和那样查询 按照 ...
- BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...
- LOJ#3097 [SNOI2019]通信 最小费用最大流+cdq分治/主席树/分块优化建图
瞎扯 我们网络流模拟赛(其实是数据结构模拟赛)的T2. 考场上写主席树写自闭了,直接交了\(80pts\)的暴力,考完出来突然发现: woc这个题一个cdq几行就搞定了! 题意简述 有\(n\)个哨站 ...
- BZOJ 1935: [Shoi2007]Tree 园丁的烦恼( 差分 + 离散化 + 树状数组 )
假如矩阵范围小一点就可以直接用二维树状数组维护. 这道题, 差分答案, 然后一维排序, 另一维离散化然后树状数组维护就OK了. ----------------------------------- ...
- bzoj1382 1935: [Shoi2007]Tree 园丁的烦恼
1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec Memory Limit: 357 MBSubmit: 1261 Solved: 578[Submit] ...
随机推荐
- Spring 的初次见面
简介: Spring Framework 是一个开源的企业级应用程序框架,为构建满足企业级需求的应用程序提供了大量的工具集.推出该框架的原因是在时候用J2EE进行开发是会提高复杂性. Spring三大 ...
- python实例 文件处理
对比Java,python的文本处理再次让人感动 #! /usr/bin/python spath="D:/download/baa.txt" f=open(spath," ...
- VI/VIM编辑器快捷键
常用快捷键: Ctrl+f 向下翻页 Ctrl+b 向上翻页 G 移动到文件最后一行 gg 移动到文件第一行 N+回车 ...
- console.js还有浏览器不支持?
今天看到项目中引入了一个插件,我超级惊讶 为什么引入console.js啊? 这个是插件的源码:https://github.com/yanhaijing/console.js 我搜到源作者对这个插件 ...
- reverse 的用法
直接对数组或是数据结构使用 #include<bits/stdc++.h> using namespace std; ]={,,,,,};//申请6个元素,下标从0开始,最后一个下标是5 ...
- Vue--由自动获取焦点引出的DOM、mounted、自定义指令
一.自动获取焦点的DOM实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- 使用php实现单点登录
1.准备两个虚拟域名 127.0.0.1 www.openpoor.com 127.0.0.1 www.myspace.com 2.在openpoor的根目录下创建以下文件 index.PHP [ ...
- Python数据分析与展示[第三周](pandas数据特征分析单元8)
数据理解 基本统计 分布/累计统计 数据特征 数据挖掘 数据排序 操作索引的排序 .sort_index() 在指定轴上排序,默认升序 参数 axis=0 column ascending=True ...
- [运维]Dell R710 raid配置 标签: raid运维 2017-04-15 19:35 581人阅读 评论(16)
Dell R系列的一些服务器,raid的配置都大同小异,公司大部分的服务器,都是Dell R710型号的,这个型号的raid界面配置起来还是很简单的,下面来跟随小编体验一下raid如何配置吧.ps:图 ...
- JS判断PC 手机端显示不同的内容
方法一: function goPAGE() { if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android ...