hdu_2795_线段树好题

//最主要的一点是:为什么会想到用线段树(非常关键)???牛人说的,哈!太神了,用一般方法超时了,我试过!其实跟huffman的解码过程很像 //此题不像一般的线段树一样给出query区间[a,b],只要遍历到node[i].l>=a&&node[i].r<=b即可,而是要遍历到叶子节点 //对h进行离散化,每一个区间的key值保存这个区间的每个叶子所剩w的最大值,query和update合为一步,其他的没什么好说的 //time:1960ms #include<iostream> #include<cstdio> #include<cmath> using namespace std; struct tree { int l,r,w; }node[600005]; int h,w,n; int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a>b?b:a; } void creat(int i,int a,int b) { node[i].l=a; node[i].r=b; node[i].w=w; if(a==b) return ; else { int mid=(a+b)/2; creat(2*i,a,mid); creat(2*i+1,mid+1,b); } } int query_update(int i,int key) //深搜要一直到达叶子 { int temp; if(node[i].w>=key) { if(node[i].l==node[i].r) { node[i].w-=key; return node[i].l; } else if(node[2*i].w>=key) { temp=query_update(2*i,key); } else { temp=query_update(2*i+1,key); } node[i].w=max(node[2*i].w,node[2*i+1].w); //保存左右孩子中最大的那个 return temp; } return -1; } int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { int m=min(h,200000); //如果超过20w就用20w,因为每一个小广告的高是1,最多也就是20w的高度 int wx; int index; creat(1,1,m); while(n--) { scanf("%d",&wx); printf("%d/n",query_update(1,wx)); } } return 0; }  

你可能感兴趣的:(tree,query)