JZOJ 5797. 2018.08.11【2018提高组】模拟A组 跳跃
你曾经梦想过你是电脑游戏中的主角吗?这个故事的主角,Branimir,现在正在做这个梦。
在Branimir的梦中,世界是由从左到右排列的N座摩天大楼组成的。对于第i座摩天大楼,我们知道摩天大楼的高度Hi和房顶金币的数量Gi。
游戏从在任何摩天大楼上跳跃开始,由几步组成。
在每一步中,Branimir都可以从他目前所在的摩天大楼向右跳(他也有可能跳过其中的几个),到一个高度不低于现在的摩天大楼。
假如Branimir在一座摩天大楼,他可以拿这座大楼的金币。
Branimir可以在任意步数之后结束游戏(0步也可以)通往下一关,但必须要收集至少K个金币。
现在要求Branimir通往下一关的方案数。两个方案当做不同当且仅当Branimir在其中一次跳过其中一座摩天大楼而另一次没有。
对于40%的数据,1<=n<=20
对于100%的数据,1<=n<=40,1<=k<=4*10^10,1<=Hi,Gi<=10^9
搜索好水题
40%部分分的话,暴力枚举选哪些就行了
100%的数据的话,n<=40,暗示折半搜索
先对1~n/2搜出所有的(hl,sl),表示选完后最右侧的楼房的高度和所有楼房的金币总和
然后搜出n/2+1~n的所有(hr,sr),表示选完后最左侧的楼房的高度和所有楼房的金币总和
然后枚举(hr,sr),再枚举hl,要满足hl<=hr且sl>=k-sr,直接二分就行了
1 %:pragma GCC optimize(2) 2 %:pragma GCC optimize(3) 3 %:pragma GCC optimize("Ofast") 4 %:pragma GCC optimize("inline") 5 %:pragma GCC optimize("-fgcse") 6 %:pragma GCC optimize("-fgcse-lm") 7 %:pragma GCC optimize("-fipa-sra") 8 %:pragma GCC optimize("-ftree-pre") 9 %:pragma GCC optimize("-ftree-vrp") 10 %:pragma GCC optimize("-fpeephole2") 11 %:pragma GCC optimize("-ffast-math") 12 %:pragma GCC optimize("-fsched-spec") 13 %:pragma GCC optimize("unroll-loops") 14 %:pragma GCC optimize("-falign-jumps") 15 %:pragma GCC optimize("-falign-loops") 16 %:pragma GCC optimize("-falign-labels") 17 %:pragma GCC optimize("-fdevirtualize") 18 %:pragma GCC optimize("-fcaller-saves") 19 %:pragma GCC optimize("-fcrossjumping") 20 %:pragma GCC optimize("-fthread-jumps") 21 %:pragma GCC optimize("-funroll-loops") 22 %:pragma GCC optimize("-fwhole-program") 23 %:pragma GCC optimize("-freorder-blocks") 24 %:pragma GCC optimize("-fschedule-insns") 25 %:pragma GCC optimize("inline-functions") 26 %:pragma GCC optimize("-ftree-tail-merge") 27 %:pragma GCC optimize("-fschedule-insns2") 28 %:pragma GCC optimize("-fstrict-aliasing") 29 %:pragma GCC optimize("-fstrict-overflow") 30 %:pragma GCC optimize("-falign-functions") 31 %:pragma GCC optimize("-fcse-skip-blocks") 32 %:pragma GCC optimize("-fcse-follow-jumps") 33 %:pragma GCC optimize("-fsched-interblock") 34 %:pragma GCC optimize("-fpartial-inlining") 35 %:pragma GCC optimize("no-stack-protector") 36 %:pragma GCC optimize("-freorder-functions") 37 %:pragma GCC optimize("-findirect-inlining") 38 %:pragma GCC optimize("-fhoist-adjacent-loads") 39 %:pragma GCC optimize("-frerun-cse-after-loop") 40 %:pragma GCC optimize("inline-small-functions") 41 %:pragma GCC optimize("-finline-small-functions") 42 %:pragma GCC optimize("-ftree-switch-conversion") 43 %:pragma GCC optimize("-foptimize-sibling-calls") 44 %:pragma GCC optimize("-fexpensive-optimizations") 45 %:pragma GCC optimize("-funsafe-loop-optimizations") 46 %:pragma GCC optimize("inline-functions-called-once") 47 %:pragma GCC optimize("-fdelete-null-pointer-checks") 48 49 #include <bits/stdc++.h> 50 using namespace std; 51 typedef long long ll; 52 const int N = 45; 53 54 int n; ll k; 55 56 struct P { 57 ll h, g; 58 } p[N]; 59 60 vector<P> pre, sub; 61 62 vector<ll> h; 63 64 map<ll, int> hsh; int cnt; 65 66 vector<ll> tl[N]; 67 68 void dfs(int now, int end, int type, ll h, ll sum, ll ext = 0) { 69 if(type == 1) { 70 if(now > end) { 71 pre.push_back((P) { h, sum }); 72 } else { 73 dfs(now + 1, end, type, h, sum); 74 if(p[now].h >= h) dfs(now + 1, end, type, p[now].h, sum + p[now].g); 75 } 76 } else { 77 if(now > end) { 78 sub.push_back((P) { ext, sum }); 79 } else { 80 dfs(now + 1, end, type, h, sum, ext); 81 if(p[now].h >= h) dfs(now + 1, end, type, p[now].h, sum + p[now].g, ext == 0 ? p[now].h : ext); 82 } 83 } 84 } 85 86 ll ans; 87 88 void sol() { 89 dfs(1, n / 2, 1, 0, 0); 90 dfs(n / 2 + 1, n, 2, 0, 0); 91 for(P t: pre) { 92 if(t.g >= k) ++ ans; 93 tl[hsh[t.h]].push_back(t.g); 94 } 95 96 for(int i = 1 ; i <= cnt ; ++ i) { 97 if(tl[i].size()) sort(tl[i].begin(), tl[i].end()); 98 } 99 100 for(P t: sub) { 101 ll hr = t.h, sr = t.g; 102 if(sr >= k) ++ ans; 103 for(ll HL: h) { 104 if(HL > hr) break; 105 ll hl = hsh[HL]; 106 if(tl[hl].back() >= k - sr) { 107 ans += tl[hl].size() - (lower_bound(tl[hl].begin(), tl[hl].end(), k - sr) - tl[hl].begin()); 108 } 109 } 110 } 111 112 cout << ans; 113 } 114 115 int main() { 116 freopen("san.in", "r", stdin); 117 freopen("san.out", "w", stdout); 118 cin >> n >> k; 119 for(int i = 1 ; i <= n ; ++ i) cin >> p[i].h >> p[i].g; 120 for(int i = 1 ; i <= n / 2 ; ++ i) h.push_back(p[i].h); 121 sort(h.begin(), h.end()); 122 h.erase(unique(h.begin(), h.end()), h.end()); 123 for(ll x: h) hsh[x] = ++ cnt; 124 if(n == 1) cout << (p[1].g >= k) << endl; 125 else sol(); 126 }