[BZOJ1935][SHOI2007]Tree 園丁的煩惱(樹狀數組)
題目描述
很久很久以前,在遙遠的大陸上有一個美麗的國家。統治著這個美麗國家的國王是一個園藝愛好者,在他的皇家花園裏種植著各種奇花異草。
有一天國王漫步在花園裏,若有所思,他問一個園丁道: “最近我在思索一個問題,如果我們把花壇擺成六個六角形,那麽……”
“那麽本質上它是一個深度優先搜索,陛下”,園丁深深地向國王鞠了一躬。
“嗯……我聽說有一種怪物叫九頭蛇,它非常貪吃蘋果樹……”
“是的,顯然這是一道經典的動態規劃題,早在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 園丁的煩惱(樹狀數組)