题意: 有一个黑板 高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[n].l=L;
segTree[n].r=R;
// segTree[n].lazy=0;
segTree[n].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[n].val > flag){
segTree[n].val=flag;
return push_up(n/2); //写了这个其实是有点怕超时的,然而好像不会有很大的影响。
}
else
return;
if(n==1)
return;
}
void push_down(int n){
segTree[n].val=max(segTree[n<<1].val,segTree[(n<<1)|1].val);
}
//void update(int l,int r,int n,int ll){
// if(segTree[n].l==l && segTree[n].r==r){
// segTree[n].lazy=1;
// segTree[n].val-=ll;
// return;
// }
// push_up(n);
// int mid=(segTree[n].l + segTree[n].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;
}