再次领教了线段树的威力。维护一个最大值,优先选择左边的,更新操作写在了查询里面。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define MAXN 105
using namespace std;
const int MAX_N= 1<<19;
int mxn,n,h,w;
int dat[MAX_N];
void build(int k,int l,int r)
{
dat[k]=w;
if(l==r) return;
build(2*k,l,(l+r)/2);
build(2*k+1,(l+r)/2+1,r);
}
void Init()
{
mxn=1;
while(mxn<h) mxn*=2;
memset(dat,0,sizeof(dat));
build(1,1,h);
}
int query(int x,int k,int l,int r)
{
if(l==r)
{
dat[k]-=x;
return l;
}
else
{
int ans=0;
if(dat[2*k]>=x) ans=query(x,2*k,l,(l+r)/2);
else ans=query(x,2*k+1,(l+r)/2+1,r);
dat[k]=max(dat[2*k],dat[2*k+1]);
return ans;
}
}
int main()
{
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
h=min(h,n);
Init();
int t;
for(int i=0;i<n;++i)
{
scanf("%d",&t);
if(dat[1]<t) printf("-1\n");
else printf("%d\n",query(t,1,1,h));
}
}
return 0;
}
后来重写了一遍。
首先h=min(h,200000),以h为结点建立线段树,树上存某个区间内宽度的最大值。这样每次查询相当于二分寻找大于t的叶结点,优先从左寻找。找到的叶结点同时要减去t,然后更新父亲结点。不存在时返回-1。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 500005
#define LEN 222222<<2
using namespace std;
int h,w,n;
struct Segment_tree
{
private:
int data[LEN],sz;
void pushup(int o)
{
data[o]=max(data[o<<1],data[o<<1|1]);
}
int myquery(int o,int L,int R,int v)
{
if(L==R)
{
data[o]-=v;
return L;
}
int M=(L+R)/2;
int res=-1;
if(v<=data[o<<1]) res=myquery(o<<1,L,M,v);
else if(v<=data[o<<1|1])res= myquery(o<<1|1,M+1,R,v);
pushup(o);
return res;
}
public:
void clear()
{
sz=h;
}
void build(int o,int L,int R)
{
if(L==R) data[o]=w;
else
{
int M=(L+R)/2;
build(o<<1,L,M);
build(o<<1|1,M+1,R);
data[o]=w;
}
}
int query(int p)
{
return myquery(1,1,sz,p);
}
};
Segment_tree tree;
int main()
{
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
int t;
h=min(h,200000);
tree.clear();
tree.build(1,1,h);
for(int i=0; i<n; ++i)
{
scanf("%d",&t);
printf("%d\n",tree.query(t));
}
}
return 0;
}