2795 線段樹點修改,求區間最大
阿新 • • 發佈:2018-12-16
題意
給你一個廣告牌的長度和寬度,和要貼的廣告數。每條廣告的長度為 1 ,輸入n條廣告的高。輸出廣告所在的行數。所有的廣告都靠左貼。
#include<cstdio> #include<algorithm> using namespace std; const int maxn=524288+10; int node[maxn]; // 存放區間最大值(最寬的哪一行) int h,w,n; void bulid(int l,int r,int rt) { node[rt]=w; // 把每一個區間初始化為 剩餘的寬度,一開始沒貼廣告所以每個區間剩餘寬度等於廣告牌的寬 if(l==r) return ; int m=(l+r)>>1; bulid(l,m,rt<<1); bulid(m+1,r,rt<<1|1); } int query(int x,int l,int r,int rt) { if(l==r) // 廣告只能貼在葉子結點區間上 每一個葉子結點代表一行 { node[rt]-=x; return l; // 這個廣告貼在第幾行(葉子節點) } int m=(l+r)>>1; int res; if(node[rt<<1]>=x) // 如果左子樹的 剩餘最大寬度 大於需要的寬度就遍歷左子樹,否則就遍歷右子樹 //正好符合先貼左邊的要求 res=query(x,l,m,rt<<1); else res=query(x,m+1,r,rt<<1|1); node[rt]=max(node[rt<<1],node[rt<<1|1]); // 更新剩餘最大寬度 return res; } int main() { int x; while(~scanf("%d%d%d",&h,&w,&n)) { if(h>n) h=n; //最多輸入n行資料,當h>n時,建n行就夠了 bulid(1,h,1); // 以位置h建樹 for(int i=0;i<n;i++) { scanf("%d",&x); if(x>node[1]) //node[1]為所有區間當中的最大值 printf("-1\n"); else printf("%d\n",query(x,1,h,1)); } } return 0; }
這道題如果不是掛在線段樹專題,我肯定不會想到用線段樹。。。