ABC266 Ex - Snuke Panic (2D)
作者:互联网
挺好的一道题(不过调了好久QAQ
方法一
比较暴力的做法。
首先,你容易想到一个 DP 状态:\(f(t,x,y)\) 表示在 \(t\) 时刻到达 \((x,y)\) 的最大收益。
转移为:
\[f(t,x,y)=\max\{f(t',x',y')|t'\leq t,y'\leq y,|x-x'|+y-y'\leq t-t'\} \]后面的限制意思就是说你必须要在这么多时间里能够走这么多路程,因为已经有 \(t'\leq t,y'\leq y\),所以就不需要加绝对值了。
但是 \(x\) 还留着绝对值,不好处理,所以向把这个绝对值拆开。
因为 \(-|x-x'|\leq |x-x'|\),所以自然有 \(-|x-x'|+y-y'\leq t-t'\)。
这样就成功地把绝对值拆成了两个限制:
- \(x-x'+y-y'\leq t-t'\)
- \(x'-x+y-y'\leq t-t'\)
对它做一个变形(即移项使 \(x,y,t\) 在一边,\(x',y',t'\) 在一边),得到:
- \(t'-x'-y'\leq t-x-y\)
- \(t'+x'-y'\leq t+x-y\)
那么你按照 \(y\) 对它排一下序,只用考虑满足上面两个性质地最大值,用二维树状数组做就行了。
时间复杂度 \(O(n\log^2 n)\)。
方法二
前面的转化还是跟上面一样的。
你按 \(y\) 排完序以后可以考虑用 CDQ 分治来做。
现在考虑问题已经知道 \([l,mid]\) 的值,如何计算出 \([mid+1,r]\) 的值。
首先需要明确,因为已经按找 \(y\) 排序过了,所以所有 \([l,mid]\) 的 \(y\) 必然不大于 \([mid+1,r]\) 的 \(y\)。
也就是说,只需要考虑 \(t'-x'-y'\leq t-x-y\) 和 \(t'+x'-y'\leq t+x-y\) 的限制即可。
对于这两个限制,可以先对 \(t-x-y\) 值排序,这样就只剩一个限制了,然后用树状数组就可以做了。
时间复杂度 \(O(n\log^2 n)\),但是常数极小,比方法一不知道快多少倍。
注意:需要添加一个点 \((0,0,0,0)\),并且在树状数组计算的时候需要将初值设为 \(-\infty\),防止转移其他的。
反思
第一个思路比较简单,只需要将转移和限制在纸上清晰地列下来就行。
方法二地 CDQ 分治比较巧妙,需要用到一些奇技淫巧。
方法一的 code:
#include<bits/stdc++.h>
//#define JERRY_JIANG
#define fi first
#define se second
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
inline int read() {
int x = 0;
bool f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= ch == '-', ch = getchar();
while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return f ? -x : x;
}
inline void print(int x) {
if(x < 0) return putchar('-'), print(-x);
if(x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
inline int lowbit(int x) {return x & -x;}
bool Memst;
int n;
struct Data {
int y, a, b, sz;
bool operator < (const Data &x) const {
if(y != x.y) return y < x.y;
if(a != x.a) return a < x.a;
if(b != x.b) return b < x.b;
return sz < x.sz;
}
};
vector<Data> datas;
vector<int> va, vb;
struct FenwickTree1D {
int Mxn;
unordered_map<int, ll> tree;
FenwickTree1D() : Mxn(0){};
FenwickTree1D(int n) : Mxn(n){};
void update(int x, ll v) {
while(x <= Mxn) {
tree[x] = max(tree[x], v);
x += lowbit(x);
}
}
ll query(int x) {
ll res = 0;
while(x > 0) {
res = max(res, tree[x]);
x -= lowbit(x);
}
return res;
}
};
struct FenwickTree2D {
int Mxn, Mxm;
vector<FenwickTree1D> tree;
FenwickTree2D(int n, int m) : Mxn(n), Mxm(m), tree(n, FenwickTree1D(m)){};
void update(int x, int y, ll v) {
while(x <= Mxn) {
tree[x].update(y, v);
x += lowbit(x);
}
}
ll query(int x, int y) {
ll res = 0;
while(x > 0) {
res = max(res, tree[x].query(y));
x -= lowbit(x);
}
return res;
}
};
bool Memed;
int main(){
fprintf(stderr, "%.3lf MB\n", (&Memst - &Memed) / 1048576.0);
#ifdef JERRY_JIANG
FILE *IN = freopen("input.in", "r", stdin);
FILE *OUT = freopen("output.out", "w", stdout);
#endif
ios::sync_with_stdio(false); cin.tie(0);
/* - input - */
n = read();
for(int i = 1; i <= n; i++) {
int t = read(), x = read(), y = read(), sz = read();
if(t - x - y >= 0 && t + x - y >= 0) {
datas.push_back({y, t - x - y, t + x - y, sz});
va.push_back(t - x - y); vb.push_back(t + x - y);
}
}
double Timst = TIME;
sort(datas.begin(), datas.end());
sort(va.begin(), va.end());
va.resize(unique(va.begin(), va.end()) - va.begin());
sort(vb.begin(), vb.end());
vb.resize(unique(vb.begin(), vb.end()) - vb.begin());
FenwickTree2D T((int)va.size() + 1, (int)vb.size() + 1);
ll ans = 0;
for(int i = 0; i < (int)datas.size(); i++) {
int y = datas[i].y, a = datas[i].a, b = datas[i].b, sz = datas[i].sz;
a = lower_bound(va.begin(), va.end(), a) - va.begin() + 1;
b = lower_bound(vb.begin(), vb.end(), b) - vb.begin() + 1;
ll cur = T.query(a, b) + (ll)sz;
ans = max(ans, cur);
T.update(a, b, cur);
}
cout << ans << '\n';
double Timed = TIME;
fprintf(stderr, "%.3lf ms\n", Timed - Timst);
return 0;
}
/*
author: Jerry_Jiang
start coding at 30/08/22 08:51
finish debugging at 30/08/22 09:53
*/
方法二的 code:
#include<bits/stdc++.h>
//#define JERRY_JIANG
#define fi first
#define se second
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
inline int read() {
int x = 0;
bool f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= ch == '-', ch = getchar();
while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return f ? -x : x;
}
inline void print(int x) {
if(x < 0) return putchar('-'), print(-x);
if(x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
inline int lowbit(int x) {return x & -x;}
bool Memst;
constexpr int N = 1e5 + 10;
int n;
pair<pii, pii> a[N];
pair<pii, int> b[N];
ll tree[N], dp[N];
void update(int x, ll v) {
while(x < N) {
tree[x] = max(tree[x], v);
x += lowbit(x);
}
}
ll query(int x) {
ll res = -0x3f3f3f3f3f3f3f3f;
while(x > 0) {
res = max(res, tree[x]);
x -= lowbit(x);
}
return res;
}
void solve(int l, int r) {
if(l == r) {
dp[l] += (ll)a[l].se.se;
return;
}
int mid = (l + r) >> 1;
solve(l, mid);
vector<int> v;
int tot = 0;
for(int i = l; i <= r; i++) {
int p = a[i].fi.se - a[i].fi.fi - a[i].se.fi, q = a[i].fi.se - a[i].fi.fi + a[i].se.fi;
b[++tot] = make_pair(make_pair(p, q), i);
v.push_back(q);
}
sort(b + 1, b + tot + 1);
sort(v.begin(), v.end());
v.resize(unique(v.begin(), v.end()) - v.begin());
for(int i = 1; i <= (int)v.size(); i++) tree[i] = -0x3f3f3f3f3f3f3f3f;
for(int i = 1; i <= tot; i++) {
int pos = lower_bound(v.begin(), v.end(), b[i].fi.se) - v.begin() + 1, id = b[i].se;
if(id <= mid) update(pos, dp[id]);
else dp[id] = max(dp[id], query(pos));
}
solve(mid + 1, r);
}
bool Memed;
int main(){
fprintf(stderr, "%.3lf MB\n", (&Memst - &Memed) / 1048576.0);
#ifdef JERRY_JIANG
FILE *IN = freopen("input.in", "r", stdin);
FILE *OUT = freopen("output.out", "w", stdout);
#endif
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i].fi.se >> a[i].se.fi >> a[i].fi.fi >> a[i].se.se;
sort(a + 1, a + n + 1);
a[0].fi.fi = a[0].fi.se = a[0].se.fi = a[0].se.se = 0;
memset(dp, -0x3f, sizeof(dp));
dp[0] = 0;
solve(0, n);
ll ans = 0;
for(int i = 1; i <= n; i++) ans = max(ans, dp[i]);
cout << ans << endl;
fprintf(stderr, "%.3lf ms\n", TIME);
return 0;
}
/*
author: Jerry_Jiang
*/
标签:2D,ch,return,leq,int,ll,ABC266,Snuke,va 来源: https://www.cnblogs.com/Jerry-Jiang/p/16638939.html