1. 程式人生 > >[BZOJ1935][SHOI2007]Tree 園丁的煩惱(樹狀數組)

[BZOJ1935][SHOI2007]Tree 園丁的煩惱(樹狀數組)

pre sample stdin turn 然而 ++ test 復制 是的

題目描述

很久很久以前,在遙遠的大陸上有一個美麗的國家。統治著這個美麗國家的國王是一個園藝愛好者,在他的皇家花園裏種植著各種奇花異草。

有一天國王漫步在花園裏,若有所思,他問一個園丁道: “最近我在思索一個問題,如果我們把花壇擺成六個六角形,那麽……”

“那麽本質上它是一個深度優先搜索,陛下”,園丁深深地向國王鞠了一躬。

“嗯……我聽說有一種怪物叫九頭蛇,它非常貪吃蘋果樹……”

“是的,顯然這是一道經典的動態規劃題,早在N元4002年我們就已經發現了其中的奧秘了,陛下”。

“該死的,你究竟是什麽來頭?”

“陛下息怒,幹我們的這行經常莫名其妙地被問到和OI有關的題目,我也是為了預防萬一啊!” 王者的尊嚴受到了傷害,這是不可容忍的。

看來一般的難題是難不倒這位園丁的,國王最後打算用車輪戰來消耗他的實力: “年輕人,在我的花園裏的每一棵樹可以用一個整數坐標來表示,一會兒,我的騎士們會來輪番詢問你某一個矩陣內有多少樹,如果你不能立即答對,你就準備走人吧!”說完,國王氣呼呼地先走了。

這下輪到園丁傻眼了,他沒有準備過這樣的問題。所幸的是,作為“全國園丁保護聯盟”的會長——你,可以成為他的最後一根救命稻草。

輸入輸出格式

輸入格式:

第一行有兩個整數n,m(0≤n≤500000,1≤m≤500000)。n代表皇家花園的樹木的總數,m代表騎士們詢問的次數。

文件接下來的n行,每行都有兩個整數xi,yi,代表第i棵樹的坐標(0≤xi,yi≤10000000)。

文件的最後m行,每行都有四個整數aj,bj,cj,dj,表示第j次詢問,其中所問的矩形以(aj,bj)為左下坐標,以(cj,dj)為右上坐標。

輸出格式:

共輸出m行,每行一個整數,即回答國王以(aj,bj)和(cj,dj)為界的矩形裏有多少棵樹。

輸入輸出樣例

輸入樣例#1: 復制
3 1
0 0 
0 1
1 0
0 0 1 1

題解
正常解法是CDQ
然而直接樹狀數組也能做
先把矩形給差分
先把y給離散
然後按x排序
可以保證x是單調增的
然後y用樹狀數組就可以了
 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using std::sort;
 6 using std::unique;
 7 using std::lower_bound;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 inline int read(){
11     #define num ch-‘0‘
12     char ch;bool flag=0;int res;
13     while(!isdigit(ch=getc()))
14     (ch==-)&&(flag=true);
15     for(res=num;isdigit(ch=getc());res=res*10+num);
16     (flag)&&(res=-res);
17     #undef num
18     return res;
19 }
20 char sr[1<<21],z[20];int C=-1,Z;
21 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
22 inline void print(int x){
23     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
24     while(z[++Z]=x%10+48,x/=10);
25     while(sr[++C]=z[Z],--Z);sr[++C]=\n;
26 }
27 const int N=500005;
28 int x[N],y[N],a[N],b[N],c[N],d[N],p[N*5];
29 int n,m,tot,cnt;
30 struct node{
31     int x,y,id,type;
32     inline void add(int a,int b,int c=0,int d=0)
33     {x=a,y=b,id=c,type=d;}
34     inline bool operator <(const node &b)const
35     {return x<b.x||(x==b.x&&type<b.type);}
36 }q[N*5];
37 int res[N],ans[N][5];
38 inline void add(int x,int val){
39     for(int i=x;i<=n;i+=i&(-i))
40     res[i]+=val;
41 }
42 inline int query(int x){
43     int ans=0;
44     for(int i=x;i;i-=i&(-i))
45     ans+=res[i];
46     return ans;
47 }
48 int main(){
49     //freopen("testdata.in","r",stdin);
50     n=read(),m=read();
51     for(int i=1;i<=n;++i){
52         x[i]=read()+1,y[i]=read()+1;
53         p[++tot]=y[i];
54     }
55     for(int i=1;i<=m;++i){
56         a[i]=read()+1,b[i]=read()+1,c[i]=read()+1,d[i]=read()+1;
57         p[++tot]=b[i],p[++tot]=d[i];
58     }
59     sort(p+1,p+1+tot);
60     tot=unique(p+1,p+1+tot)-p-1;
61     for(int i=1;i<=n;++i){
62         y[i]=lower_bound(p+1,p+1+tot,y[i])-p;
63         q[++cnt].add(x[i],y[i]);
64     }
65     for(int i=1;i<=m;++i){
66         b[i]=lower_bound(p+1,p+1+tot,b[i])-p;
67         d[i]=lower_bound(p+1,p+1+tot,d[i])-p;
68         q[++cnt].add(a[i]-1,b[i]-1,i,1),q[++cnt].add(a[i]-1,d[i],i,2);
69         q[++cnt].add(c[i],b[i]-1,i,3),q[++cnt].add(c[i],d[i],i,4);
70     }
71     sort(q+1,q+1+cnt);
72     for(int i=1;i<=cnt;++i){
73         if(!q[i].type) add(q[i].y,1);
74         else ans[q[i].id][q[i].type]=query(q[i].y);
75     }
76     for(int i=1;i<=m;++i){
77         int k=ans[i][4]-ans[i][3]-ans[i][2]+ans[i][1];
78         print(k);
79     }
80     Ot();
81     return 0;
82 }

[BZOJ1935][SHOI2007]Tree 園丁的煩惱(樹狀數組)