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;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,Q,c[N],mp[N];
int m,qid;
struct Operation{
    int x,y,v,id;
    int qid,op;
    Operation():op(0){}
    Operation(int x,int y,int v,int id,int qid,int op):
        x(x),y(y),v(v),id(id),qid(qid),op(op){}
    bool operator <(const Operation &r)const{
        return x==r.x?op<r.op:x<r.x;
    }
}a[N];
void devideQuery(){
    int x1=read()-1,y1=read()-1,x2=read(),y2=read();
    mp[++mp[0]]=y1;mp[++mp[0]]=y2;
    qid++;
    m++;a[m]=Operation(x2,y2,1,m,qid,1);
    m++;a[m]=Operation(x1,y2,-1,m,qid,1);
    m++;a[m]=Operation(x2,y1,-1,m,qid,1);
    m++;a[m]=Operation(x1,y1,1,m,qid,1);
}
void iniMP(){
    sort(mp+1,mp+1+mp[0]);
    int p=0;
    mp[++p]=mp[1];
    for(int i=2;i<=mp[0];i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
    mp[0]=p;
}
int Bin(int v){
    int l=1,r=mp[0];
    while(l<=r){
        int mid=(l+r)>>1;
        if(v==mp[mid]) return mid;
        else if(v<mp[mid]) r=mid-1;
        else l=mid+1;
    }
    return 0;
}
inline int lowbit(int x){return x&-x;}
void add(int p,int v){for(;p<=n;p+=lowbit(p)) c[p]+=v;}
int sum(int p){
    int re=0;
    for(;p;p-=lowbit(p)) re+=c[p];
    return re;
}
int ans[N];
void solve(){
    for(int i=1;i<=m;i++){
        if(!a[i].op) add(a[i].y,1);
        else ans[a[i].qid]+=a[i].v*sum(a[i].y);
    }
    for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);
}
int main(){
    freopen("in","r",stdin);
    n=read();Q=read();
    for(int i=1;i<=n;i++) a[++m].x=read(),mp[++mp[0]]=a[m].y=read();
    for(int i=1;i<=Q;i++) devideQuery();
    iniMP();
    for(int i=1;i<=m;i++) a[i].y=Bin(a[i].y);
    sort(a+1,a+1+m);
    solve();
}
时间: 2024-10-27 11:52:11

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

BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组

题目大意:给出平面中的一些点,询问平面中的一些矩形中有多少点. 思路:正常应该是二维树状数组,然后数据范围太大.所以就只能按照一个坐标排序,另一个坐标跑树状数组.注意离线操作,一个问题拆成4个. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 500010 #define RANGE 10000010 using n

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,

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 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……”

BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

题目大意:给定平面上的一些点,多次询问某个矩形中有多少个点 将每个询问拆成4个 然后把所有询问和点都按照横坐标排序 对于每个询问,将所有x值小于等于这个询问的x的点的y值加入树状数组 然后在树状数组上查询小于等于这个询问的y值的点的数量 别被1000W吓到了 如果不爆内存的话1E也是能搞的 套个log就没多少了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

BZOJ1935: [Shoi2007]Tree 园丁的烦恼

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

BZOJ 1452: [JSOI2009]Count (二维树状数组)

Description Input Output Sample Input Sample Output 1 2 HINT 二维树状数组的简单应用,c数组的第一维坐标相当于哈希.如果是修改操作,修改前 将当前的值的个数以及祖先都减1, 修改后将个数加1. #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include

HDU 3333 Turing Tree 树状数组 离线查询

题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少. 思路还是比较难想的,起码对于蒟蒻我来说. 将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的). 然后就是简单的点更新,区间求和问题了- #include <cstdio> #include <cstring> #include <iostream> #include <map> #include

HDU 3333 Turing Tree(树状数组离线处理)

HDU 3333 Turing Tree 题目链接 题意:给定一个数组,每次询问一个区间,求出这个区间不同数字的和 思路:树状数组离线处理,把询问按右端点判序,然后用一个map记录下每个数字最右出现的位置,因为一个数字在最右边出现,左边那些数字等于没用了,利用树状数组进行单点修改区间查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <map> using n