hdu 6183 線段樹的空間優化
阿新 • • 發佈:2018-12-01
題意:
一個空的座標系,有④種操作:①1 x y c表示在(x, y)點染上顏色c;②2 X y1 y2表示查詢在(1, y1)到(X, y2)範圍內有多少種不同的顏色:
③0表示清屏;④3表示程式退出(0<=x, y<=1000000, 0<=c<=50)
思路:開五十個線段樹(一種顏色一個),以y為下表,儲存min x,(因為查詢x固定1---X)然後暴力查詢50個就好了
但是顯然碰到了一個問題,1e6 開50個線段樹顯然不現實。。所以需要空間優化一下。。。這裡我們考慮動態來開闢線段樹,有效的節點進行分配,無效則不分配。。。提問,這樣空間為什麼是合理的呢?其實因為一個add 最多開logn個節點,單組只有1.5e5次查詢,顯然,最多也就只開了qlogn個。那麼這樣空間複雜度就是合理的了。。具體動態開闢的實現也非常簡單,類比trie,見程式碼。
程式碼:
#include<bits/stdc++.h> using namespace std; #define MEM(x,y) memset(x,y,sizeof(x)); const int maxn=3e6+10; int root[55]; int L[maxn],R[maxn],tot,sum[maxn]; void update(int &rt,int idx,int val,int l,int r){ if(rt==-1) rt=tot++; sum[rt]=min(val,sum[rt]); if(l==r) return; int mid=(l+r)/2; if(idx<=mid) update(L[rt],idx,val,l,mid); else update(R[rt],idx,val,mid+1,r); return; } int query(int rt,int l,int r,int ll,int rr){ int ret=1e9; if(rt==-1) return ret; if(ll==l&&rr==r) return sum[rt]; int mid=(ll+rr)/2; if(r<=mid) ret=query(L[rt],l,r,ll,mid); else if(l>mid) ret=query(R[rt],l,r,mid+1,rr); else ret=min(query(L[rt],l,mid,ll,mid),query(R[rt],mid+1,r,mid+1,rr)); return ret; } int main(){ int t,n,op,x,y,y1,y2,c,ret; while(scanf("%d",&op)){ if(op==0){ MEM(L,-1);MEM(R,-1); for(int i=0;i<maxn;++i) sum[i]=1e9; tot=52; } else if(op==1){ scanf("%d%d%d",&x,&y,&c); update(c,y,x,1,1e6); } else if(op==2){ scanf("%d%d%d",&x,&y1,&y2); ret=0; for(int i=0;i<=50;++i) ret+=(query(i,y1,y2,1,1e6)<=x); printf("%d\n",ret); } else if(op==3) break; } }