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

题目链接

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

//119964kb  4380ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define lb(x) (x)&-(x)
const int N=5e5+5;

int n,m,Ans[N];
struct Operation
{
    int id,x,y,val;//id=0:Modify val=1/-1
    Operation() {;}
    Operation(int i,int X,int Y,int v): id(i),x(X),y(Y),val(v) {};
    bool operator <(const Operation &a)const{
        return x==a.x?id<a.id:x<a.x;
    }
}q[N*5],tmp[N*5];

namespace BIT
{
    int Max,t[10000005];
    void Add(int p,int v){
        while(p<=Max) t[p]+=v,p+=lb(p);
    }
    int Query(int p){
        int res=0;
        while(p) res+=t[p],p-=lb(p);
        return res;
    }
}
inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
void CDQ(int l,int r)
{
    if(l<r)
    {
        int m=l+r>>1; CDQ(l,m), CDQ(m+1,r);
        int p1=l,p2=m+1,t=0;
        while(p1<=m&&p2<=r)
        {
            if(q[p1]<q[p2])
            {
                if(!q[p1].id) BIT::Add(q[p1].y,1);
                tmp[t++]=q[p1++];
            }
            else
            {
                if(q[p2].id) Ans[q[p2].id]+=q[p2].val*BIT::Query(q[p2].y);
                tmp[t++]=q[p2++];
            }
        }
        if(p1<=m)
        {//特判下少计算些
            for(int i=l; i<p1; ++i)
                if(!q[i].id) BIT::Add(q[i].y,-1);
            while(p1<=m) tmp[t++]=q[p1++];
        }
        else
        {
            while(p2<=r)
            {
                if(q[p2].id) Ans[q[p2].id]+=q[p2].val*BIT::Query(q[p2].y);
                tmp[t++]=q[p2++];
            }
            for(int i=l; i<=m; ++i)
                if(!q[i].id) BIT::Add(q[i].y,-1);
        }
        for(int i=0; i<t; ++i) q[l+i]=tmp[i];
//      for(int i=l; i<=r; ++i) q[i]=tmp[i];//这样竟然会慢 玄学
    }
}

int main()
{
    n=read(),m=read();
    int qcnt=0,mx=0;
    for(int x,y,i=1; i<=n; ++i)
        x=read()+1,y=read()+1, mx=std::max(mx,y), q[++qcnt]=Operation(0,x,y,0);//将坐标改为[1,1e7+7]
    for(int a,b,c,d,i=1; i<=m; ++i)
    {
        a=read()+1,b=read()+1,c=read()+1,d=read()+1;
        mx=std::max(mx,std::max(b,d));//当然要和查询区域取max。。不然边上的怎么更新呢
        q[++qcnt]=Operation(i,a-1,d,-1), q[++qcnt]=Operation(i,a-1,b-1,1);
        q[++qcnt]=Operation(i,c,b-1,-1), q[++qcnt]=Operation(i,c,d,1);
    }
    BIT::Max=mx;
    CDQ(1,qcnt);
    for(int i=1; i<=m; ++i) printf("%d\n",Ans[i]);

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/8576000.html

时间: 2024-08-12 22:42:30

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

BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 [树状数组 离线 离散化]

传送门 刚才我还在郁闷网上怎么没人用$CDQ$分治做 突然发现根本没有时间序.... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=3e6+5; inline int read(){ char c=getchar();int x=0,f=1; whi

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

1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 1261  Solved: 578[Submit][Status][Discuss] Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: "最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么--&

1935: [Shoi2007]Tree 园丁的烦恼

1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 648  Solved: 273[Submit][Status][Discuss] Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……”

BZOJ1935: [Shoi2007]Tree 园丁的烦恼

1935: [Shoi2007]Tree 园丁的烦恼 Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: "最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么--" "那么本质上它是一个深度优先搜索,陛下",园丁深深地向国王鞠了一躬. "嗯--我听说有一种怪物叫九头蛇,它非常贪吃苹果树--" &

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N行,每

BZOJ3262/洛谷P3810 陌上花开 CDQ分治 三维偏序 树状数组

原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 落谷P3810 题意 有$n$个元素,第$i$个元素有$a_i$.$b_i$.$c_i$三个属性,设$f(i)$表示满足$a_j\leq a_i$且$b_j\leq b_i$且$c_j\leq c_i$的$j$的数量.对于$d\in [0,n)$,求$f(i)=d$的数量. $n\leq 100000,max\{a_i,b_i,c_i|i

【算法】CDQ分治 -- 三维偏序 &amp; 动态逆序对

初次接触CDQ分治,感觉真的挺厉害的. 整体思路即分而治之,再用之前处理出来的答案统计之后的答案. 大概流程是: 对于区间 l ~ r : 1.处理 l ~mid, mid + 1 ~ r 的答案 2.分别排序规整 3.计算 l ~ mid 中每一个数对 mid + 1 ~ r 中的答案的贡献, 累加 4.得到区间l ~ r的答案 CDQ分治我一共也才做了两道题目, 就一起整理在这里了.大体都差不多,CDQ+树状数组分别维护两个维度. 1.三维偏序 #include <bits/stdc++.h

CDQ分治 三维偏序

这应该是一道CDQ分治的入门题目 我们知道,二维度的偏序问题直接通过,树状数组就可以实现了,但是三维如何实现呢? 我记得以前了解过一个小故事,应该就是分治的. 一个皇帝,想给部下分配任务,但是部下太多,他也无从下手于是他这个任务分给宰相,宰相也不怎么清楚,于是他又分给他的手下,这么一直分啊分啊,分到每一个人头顶上的时候 每个人知道自己要干什么,于是他把它的信息交给他的上级,上级有了这些数据后,他处理了交给他的上级...这么一直交啊...国王最后成功的分配这些任务. CDQ分治也是一样,在这里,首

【BZOJ1935/4822】[Shoi2007]Tree 园丁的烦恼/[Cqoi2017]老C的任务 树状数组

题意:两道题差不多,都是给你一堆平面上的点,每个点有权值,然后m次询问求某一矩形区域内的点权和 题解:先离散化,然后将询问拆成左右两条线段,然后将点和这些线段一起按x坐标排序,在y轴上维护树状数组.然后询问的答案就是两条线段上点权和之差 BZOJ1935: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int