您的位置:首页 > 其它

hdu 2795--简单线段树

2016-03-04 20:09 393 查看
题意: 有一个黑板 高h,宽w。 1<=h,w<=10^9 ,现在要贴n个广告上去 n<200000,每一个广告高都是1,然后会输入每一个广告的宽度。 广告会尽量的往上往右贴,贴广告的order按输入的顺序,没输入一个广告求贴在第几行。

这题想了大概有30分钟,一开始想h和w 太大了,根本开不了数组,就更不用提建树了。后来发现就每一个广告单独贴一行也只需要200000行,所以如果可以 以行来建立线段树。 如果h>n 那么以h 否则以n (建树)!

然后又仔细想了想,用val 来表示某区间可容纳的最大的长度。都初始化为w(宽度),然后对于每一个广告,我们写在查询里面,于是这题 应该是可以写粗来的-。- 详细的东西就写在代码里面了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define pfn printf("\n")
#define sf  scanf
#define pf  printf
#define fr(i,n) for(int i=0;i<n;i++)
#define INF 0x7fffffff   //INT_MAX
#define inf 0x3f3f3f3f   //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
const int MAXN = 200005;
struct node{
int l,r;
//int lazy;
int val;  //l-r行可以存的最大空间
}segTree[MAXN*4];
int h,w;
void build(int L,int R,int n){
segTree
.l=L;
segTree
.r=R;
//    segTree
.lazy=0;
segTree
.val=w;
if(L==R)
return;
int mid=(L+R)/2;
build(L,mid,2*n);
build(mid+1,R,2*n+1);
}
void push_up(int n){   //刚开始没有写这个函数,这里是需要向上更新的,这个错误检查到修改 弄半个小时
int flag;
if(n==0)
return;
flag=max(segTree[n<<1].val,segTree[(n<<1)|1].val);
if(segTree
.val > flag){
segTree
.val=flag;
return push_up(n/2);  //写了这个其实是有点怕超时的,然而好像不会有很大的影响。
}
else
return;
if(n==1)
return;
}
void push_down(int n){
segTree
.val=max(segTree[n<<1].val,segTree[(n<<1)|1].val);
}

//void update(int l,int r,int n,int ll){
//    if(segTree
.l==l && segTree
.r==r){
//      segTree
.lazy=1;
//      segTree
.val-=ll;
//      return;
//    }
//    push_up(n);
//    int mid=(segTree
.l + segTree
.r)/2;
//    if(r<=mid) update(l,r,n<<1,ll);
//    else if(l>mid) update(l,r,(n<<1)|1,ll);
//    else{
//        update(l,mid,n<<1,ll);
//        update(mid+1,r,(n<<1)|1,ll);
//    }
//}
int query(int i,int u){
if(u>segTree[i].val)      //刚开始写在下面了,减去一遍再比较,这不是sb吗?
return -1;
if(segTree[i].val>=u && segTree[i].l==segTree[i].r){
segTree[i].val-=u;
push_up(i/2);     //修改了线段树中的某一个节点的剩余值后朝上更新。
return segTree[i].l;
}
if(u<=segTree[i<<1].val) return query(i<<1,u);   //如果可以向左,先向左,因为更靠近上面的行
else return query((i<<1)|1,u);
}
int main()
{
int t;
//freopen("1.txt","r",stdin);
while(~scanf("%d %d %d",&h,&w,&t)){
if(t<=h) build(1,t,1);
else build(1,h,1);
for(int num=1;num<=t;num++){
int w;
scanf("%d",&w);
printf("%d\n",query(1,w));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: