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] ...
随机推荐
- java ssh框架全局变量,比如ip黑名单,毕竟比去数据库查询要快的没边儿
https://blog.csdn.net/qq_41942909/article/details/80840915 首先在springservlet配置文件中添加一个bean <bean id ...
- GIT生成公钥和私钥
转载至:https://blog.csdn.net/gwz1196281550/article/details/80268200 打开 git bash! git config --global us ...
- linux源码安装
以安装xxx.tar.gz为例: 源码存放位置:/usr/local/src/ 安装路径:/usr/local/xxx/ 配置文件存放位置:/usr/local/xxx/etc/ 可执行文件存放位置: ...
- AOP Aspect 统一日志、异常处理、数据格式 【转】
package com.gsww.chis.aop; import java.util.Arrays; import com.google.common.base.Throwables; import ...
- 使用 store 来优化 React 组件
在使用 React 编写组件的时候,我们常常会碰到两个不同的组件之间需要共享状态情况,而通常的做法就是提升状态到父组件.但是这样做会有一个问题,就是尽管只有两个组件需要这个状态,但是因为把状态提到了父 ...
- php怎么自动加载
在 PHP 代码的顶部你是不是经常看到这样的代码. require 'lionis.php'; require 'is.php'; require 'cool.php'; 如果只是引入几个 PHP 脚 ...
- 浅谈Android开机启动速度优化(含应用程序启动速度优化)
众所周知Android开机启动速度较慢,于是如何加快启动速度便成为一个值得讨论的问题. 在查阅过许多资料后(特别是Google Group的android-platform),我整理总结出下面几点基本 ...
- mysql存储过程小解
mysql 存储过程 1.创建语法 delimiter $$ --$$表示改变默认的分隔符,代表以下为存储过程,不然会以SQL的方式执行 drop procedure if exists pro_na ...
- 重温Observer模式--热水器·改
引言 在 C#中的委托和事件 一文的后半部分,讲述了Observer(观察者)模式,并使用委托和事件实现了这个模式.实际上,不使用委托和事件,一样可以实现Observer模式.在本文中,我将使用GOF ...
- Sublime text 3 如何格式化HTML/css/js代码
Sublime Text 3 安装Package Control 原来Subl3安装Package Control很麻烦,现在简单的方法来了 一.简单的安装方法 使用Ctrl+`快捷键或者通过Vi ...