代码依然参考胡浩神:
说说思路吧,因为n最大有20W,所以可以把每一行当作线段树的叶子(因为n可能小于h,所以只需要最小的那个建树就可以了),每一个叶子的值则是w;
要保证 announcements 是贴在最上面的,而且是最左边的(这点无需考虑,因为是按照读入的顺序来的),要保证是贴在最上面,所以优先向左子树搜索,即当前结点的左子树值(代表左子树下有叶子的值是大于wi的)大于wi,就搜索左子树,这样只要在搜索出来的时候直接更新就可以了......
不得不说代码相似度和胡浩神的到了100% 你妹 我真是自己敲的啊!!
#include <iostream> #include <fstream> #include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <string.h> #include <vector> #include <bitset> #include <cmath> #include <queue> #include <stack> #include <set> #include <ctime> #include <map> #include <limits> #define LL long long #define Vi vector<int> #define Si set<int> #define readf freopen("input.txt","r",stdin) #define writef freopen("output.txt","w",stdout) #define FF(i,a) for(int i(0); i < (a); i++) #define FD(i,a) for(int i(a); i >= (1); i--) #define FOR(i,a,b) for(int i(a);i <= (b); i++) #define FOD(i,a,b) for(int i(a);i >= (b); i--) #define PD(a) printf("%d",a) #define SET(a,b) memset(a,b,sizeof(a)) #define SD(a) scanf("%d",&(a)) #define LN printf("\n") #define PS printf(" ") #define pb push_back #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const double pi = acos(-1.0); const int maxn = 200001; const int INF = 99999999; const int dx[]={0,1,0,-1}; const int dy[]={1,0,-1,0}; using namespace std; int W,H,N; int Max[maxn<<2]; void PushUP(int rt){ Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); } void build(int l,int r,int rt){ Max[rt]=W; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson); } int query(int x,int l,int r,int rt){ // ym hh神 结合的太巧妙了,自己绝对想不到 if(l==r){ Max[rt]-=x; return r; } int m=(l+r)>>1; int ret=(Max[rt<<1] >=x ) ? query(x,lson):query(x,rson); PushUP(rt); return ret; } int main() { while (~scanf("%d%d%d",&H,&W,&N)) { if (H > N) H = N; build(1 , H , 1); while (N--) { int x; scanf("%d",&x); if (Max[1] < x) puts("-1"); else printf("%d\n",query(x , 1 , H , 1)); } } return 0; }