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分治/主席树的更多相关文章

  1. BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 +CDQ分治

    1935: [Shoi2007]Tree 园丁的烦恼 参考与学习:https://www.cnblogs.com/mlystdcall/p/6219421.html 题意 在一个二维平面中有n颗树,有 ...

  2. BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)

    题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 43 ...

  3. BZOJ1935:[SHOI2007]Tree 园丁的烦恼(CDQ分治)

    Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: ...

  4. BZOJ 1935 Tree 园丁的烦恼 (树状数组)

    题意:中文题. 析:按x排序,然后用树状数组维护 y 即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000" ...

  5. bzoj 1935 Tree 园丁的烦恼

    题目大意: 一些点,每次查询一个矩形内有多少个点 思路: 因为空间太大 所以不能用什么二维树状数组 需要把这些点和所有查询的矩阵的左下和右上离线下来 先离散化 然后每个子矩阵像二维前缀和那样查询 按照 ...

  6. BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...

  7. LOJ#3097 [SNOI2019]通信 最小费用最大流+cdq分治/主席树/分块优化建图

    瞎扯 我们网络流模拟赛(其实是数据结构模拟赛)的T2. 考场上写主席树写自闭了,直接交了\(80pts\)的暴力,考完出来突然发现: woc这个题一个cdq几行就搞定了! 题意简述 有\(n\)个哨站 ...

  8. BZOJ 1935: [Shoi2007]Tree 园丁的烦恼( 差分 + 离散化 + 树状数组 )

    假如矩阵范围小一点就可以直接用二维树状数组维护. 这道题,  差分答案, 然后一维排序, 另一维离散化然后树状数组维护就OK了. ----------------------------------- ...

  9. bzoj1382 1935: [Shoi2007]Tree 园丁的烦恼

    1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 1261  Solved: 578[Submit] ...

随机推荐

  1. cvc-elt.1: 找不到元素 'beans' 的声明。springmvc netbeans maven

    搭建最基本的框架,出现问题,提示cvc-elt.1: 找不到元素 'beans' 的声明. HTTP Status 500 - Servlet.init() for servlet spring th ...

  2. Flask中的session机制

    cookie和sessioncookie:网站中,http请求是无状态的,第一次和服务器连接后并且登陆成功后,第二次请求服务器依然不能知道当前请求是哪个用户.cookie的出现就是解决了改问题,第一次 ...

  3. 删除 java代码中所有的注释

    删除 java代码中所有的注释.java public class CleanCommons { private static Pattern pattern = Pattern.compile(&q ...

  4. centos 安装nginx + 多个tomcat负载均衡

    今天在centos上安装了两个tomcat和nginx,进行配置.今天记录的只是最基本的实现测试.(不包含使用redis进行session共享) Nginx 是一款轻量级的Web 服务器/反向代理服务 ...

  5. Vue.js NPM 安装方法

    由于 npm 安装速度慢,本教程使用了淘宝的镜像及其命令 cnpm,安装使用介绍参照:使用淘宝 NPM 镜像. npm 版本需要大于 3.0,如果低于此版本需要升级它: # 查看版本 $ npm -v ...

  6. 浅谈mybatis中#{}和${}的区别

    #{}:表示占位符,如果获取简单类型,#{}中可以使用value或其它名称.有效防止sql注入.使用#{}设置参数无需考虑参数的类型. 如果使用#{}比较日期字段,select* from table ...

  7. Django项目:CRM(客户关系管理系统)--12--05PerfectCRM实现King_admin注册功能获取内存01

    #base_admin.py #Django admin 注册功能的形式 # sites = { # 'crm':{ # 'customers':CustomerAdmin, # 'customerf ...

  8. 统计Linux下的CPU状态信息

    def cpu(): all_cpus=[] with open('e:/cpu.txt') as f: core={} for line in f.readlines(): ab=line.spli ...

  9. arcgis几何对象

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. phpExcel 操作示例

    片段 1 片段 2 phpExcel 操作示例 <?php //写excel //Include class require_once('Classes/PHPExcel.php'); requ ...