(思维+二分+dp)C. 1D Sokoban

C. 1D Sokoban

思路参考

思路

\(我们去枚举每一个b[i]为k,将其作为向右推箱子走到的最远的下标,那么答案就有左右两部分:\)

  • \(右边:最远动过的箱子到k,那么对于初始位置\ge k且处于特殊位置的箱子要算入答案.f[i]表示从i到n箱子已经在特殊位置的个数.\)
  • \(左边: 对于每一个k,先统计\le k的箱子有多少个,此处用到第一次二分.\\左边只有num个箱子,所以对位置k,最左只用考虑到k-num这个位置\\于是求出出现\ge k-num的第一个数的下标left,此处用到第二次二分.\)
  • \(ans=max(ans,i-left+1+f[i+1])\)
  • \(由于可以不推,所以ans至少是f[0].\)
  • \(左右两边都是独立的,把左边放到右边来做.\)
  • \(upper\_bound()返回第一个\gt x的数.lower\_bound()返回第一个\ge x的数.\)
代码
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 2e5 + 7;
int f[N];

int cal(VIT a, VIT b) {
    memset(f, 0, sizeof f);
    unordered_map<int, int> mp;
    int n = a.size(), m = b.size();
    for (int i = 0; i < n; ++i) mp[a[i]] = 1;
    for (int i = m - 1; i >= 0; --i) f[i] = f[i + 1] + mp[b[i]];
    int ans = f[0];
    for (int i = 0; i < m; ++i) {
        int num = upper_bound(a.begin(), a.end(), b[i]) - a.begin();
        int left = lower_bound(b.begin(), b.end(), b[i] - num + 1) - b.begin();
        ans = max(ans, i - left + 1 + f[i + 1]);
    }
    return ans;
}

int main() {
    //freopen("in.txt", "r", stdin);
    IO;
    int _;
    cin >> _;
    while (_--) {
        int n, m;
        cin >> n >> m;
        VIT a_pos, a_neg, b_pos, b_neg;
        for (int i = 0; i < n; ++i) {
            int x;
            cin >> x;
            if (x > 0) a_pos.pb(x);
            else a_neg.pb(-x);
        }
        for (int i = 0; i < m; ++i) {
            int x;
            cin >> x;
            if (x > 0) b_pos.pb(x);
            else b_neg.pb(-x);
        }
        reverse(a_neg.begin(), a_neg.end());
        reverse(b_neg.begin(), b_neg.end());
        int ans = cal(a_pos, b_pos) + cal(a_neg, b_neg);
        cout << ans << '\n';
    } 
    return 0;
}
 
posted @ 2021-03-06 20:10  phr2000  阅读(185)  评论(0编辑  收藏  举报