Longest Increasing Subsequence
考虑类似 LIS 的 DP 做法,设
考虑
其中
首先
此外,
那么
那么 DP 转移为
把
// LUOGU_RID: 119204826
// LUOGU_RID: 119190526
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <vector>
#include <unordered_map>
using namespace std;
#define Cobi lower_bound
#define ll long long
#define Dopi dp
const int N = 6e5 + 25;
int n, m, k;
ll a[N], b[N], s[N];
vector<int> v;
int from[N];
int s2[N];
struct Node
{
ll id, val, s, s2, ns2;
Node() = default;
Node(int id, int s, int s2, int ns2, int val)
: id(id), s(s), s2(s2), ns2(ns2), val(val)
{
}
}p[N], tmp[N];
bool cmp1(const Node& a, const Node& b)
{
return a.id < b.id;
}
bool cmp2(const Node& a, const Node& b)
{
return a.val < b.val;
}
class Bit
{
public:
long long tr[N];
ll lowbit(ll x)
{
return x & -x;
}
void update(ll x, ll v) // Good luck in your first contest and you will meet zcw
{
while (x < N)
{
tr[x] = max(tr[x], v);
x += lowbit(x);
}
}
ll query(int x)
{
ll res = -2e10;
while (x)
{
res = max(res, tr[x]);
x -= lowbit(x);
}
return res;
}
void CLEAR(ll x)
{
while (x < N)
{
tr[x] = -2e10;
x += lowbit(x);
}
}
}bt;
long long Dopi[N];
int f[N], na[N], idx, ns[N];
int ra[N];
int ispre[N], lst[N];
int fans[N], rrp[N];
bool isp[N];
// min(s_r - s_{l-1}, s2_{a_r-1}-s2_{al})
// s_r - s_{l-1} <= s2_{a_r-1}-s2_{al} => s2_{al}-s_{l-1} <= s2_{a_r-1}-s_r (-s_{l-1})
// s2_{a_r-1}-s2_{al} <= s_r - s_{l-1} => s_{l-1} - s2_{al} <= s_r - s2_{a_r-1} (-s2_{a_l})
void cdq(int l, int r)
{
if (l == r) return;
sort(p + l, p + r + 1, cmp1);
for (int i = l; i <= r; i++) tmp[i] = p[i];
int mid = l + r >> 1;
cdq(l, mid);
sort(p + l, p + mid + 1, cmp2);
sort(p + mid + 1, p + r + 1, cmp2);
int i = l, j = mid + 1;
unordered_map<int, int> mp, mp2;
while (j <= r)
{
while (i <= mid && p[i].val < p[j].val)
{
bt.update(p[i].s2 - p[i].s + 200000, Dopi[p[i].id] - p[i].s);
if (!mp.count(Dopi[p[i].id] - p[i].s))
{
mp[Dopi[p[i].id] - p[i].s] = p[i].id;
mp2[Dopi[p[i].id] - p[i].s] = p[i].s2 - p[i].s;
}
else if (p[i].s2 - p[i].s < mp2[Dopi[p[i].id] - p[i].s])
{
mp[Dopi[p[i].id] - p[i].s] = p[i].id;
mp2[Dopi[p[i].id] - p[i].s] = p[i].s2 - p[i].s;
}
i++;
}
long long g = bt.query(p[j].ns2 - p[j].s + 200000);
long long nv = g + 1 + p[j].s;
if (nv > Dopi[p[j].id])
{
Dopi[p[j].id] = nv;
lst[p[j].id] = mp[g];
}
else if (nv == Dopi[p[j].id])
{
lst[p[j].id] = min(lst[p[j].id], mp[g]);
}
j++;
}
for (int g = l; g <= mid; g++)
{
bt.CLEAR(p[g].s2 - p[g].s + 200000);
}
i = l, j = mid + 1;
mp.clear();
mp2.clear();
while (j <= r)
{
while (i <= mid && p[i].val < p[j].val)
{
bt.update(p[i].s - p[i].s2 + 200000, Dopi[p[i].id] - p[i].s2);
if (!mp.count(Dopi[p[i].id] - p[i].s2))
{
mp[Dopi[p[i].id] - p[i].s2] = p[i].id;
mp2[Dopi[p[i].id] - p[i].s2] = p[i].s - p[i].s2;
}
else if (p[i].s - p[i].s2 < mp2[Dopi[p[i].id] - p[i].s2])
{
mp[Dopi[p[i].id] - p[i].s2] = p[i].id;
mp2[Dopi[p[i].id] - p[i].s2] = p[i].s - p[i].s2;
}
i++;
}
long long g = bt.query(p[j].s - p[j].ns2 + 200000);
long long nv = g + 1 + p[j].ns2;
if (nv > Dopi[p[j].id])
{
Dopi[p[j].id] = nv;
lst[p[j].id] = mp[g];
}
else if (nv == Dopi[p[j].id])
{
lst[p[j].id] = min(lst[p[j].id], mp[g]);
}
j++;
}
for (int g = l; g <= mid; g++)
{
bt.CLEAR(p[g].s - p[g].s2 + 200000);
}
for (int i = l; i <= r; i++)
{
p[i] = tmp[i];
}
cdq(mid + 1, r);
}
signed main()
{
//freopen("D:\\111.txt", "w", stdout);
ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
cin >> n;
for (int i = 1; i < N; i++) bt.CLEAR(i);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
v.emplace_back(a[i]);
}
cin >> k;
for (int i = 1; i <= k; i++)
{
cin >> b[i];
v.emplace_back(b[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for (int i = 1; i <= n; i++)
{
int p = a[i];
a[i] = Cobi(v.begin(), v.end(), a[i]) - v.begin() + 1;
ra[a[i]] = p;
}
multiset<int> st;
for (int i = 1; i <= k; i++)
{
int p = b[i];
b[i] = Cobi(v.begin(), v.end(), b[i]) - v.begin() + 1;
ra[b[i]] = p;
st.insert(b[i]);
}
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + (ra[a[i]] == -1);
}
for (int i = 1; i <= k; i++)
{
s2[b[i]] = 1;
//cout << "!!: " << b[i] << "\n";
}
for (int i = 1; i < N; i++) s2[i] += s2[i - 1];
//cout << "s: ";
//for (int i = 1; i <= n; i++) cout << s[i] << " ";
//cout << "\ns2: ";
//for (int i = 1; i <= n + k; i++) cout << s2[i] << " ";
//cout << "\n";
for (int i = 1; i <= n; i++)
{
if (ra[a[i]] != -1)
{
na[++idx] = a[i];
ns[idx] = s[i];
//cout << na[idx] << " " << ns[idx] << "\n";
rrp[idx] = i;
}
}
na[0] = 0, na[++idx] = n + k + 5;
ns[idx] = s[n];
rrp[idx] = n + 1;
rrp[0] = 0;
Dopi[0] = 1;
p[0] = Node(0, 0, 0, 0, 0);
for (int i = 1; i <= idx; i++)
{
Dopi[i] = 1;
lst[i] = i;
p[i] = Node(i, ns[i], s2[na[i]], s2[na[i] - 1], na[i]);
//cout << "!!: " << i << " " << ns[i] << " " << s2[na[i]] << "\n";
}
/*for (int i = 1; i <= idx; i++)
{
Dopi[i] = 1;
lst[i] = i;
for (int j = 0; j < i; j++)
{
if (na[j] < na[i])
{
//cout << i << " " << j << " " << ns[i] << endl;
if (Dopi[j] + max(0LL, min(ns[i] - ns[j], s2[na[i] - 1] - s2[na[j]])) + 1 >= Dopi[i])
{
Dopi[i] = Dopi[j] + max(0LL, min(ns[i] - ns[j], s2[na[i] - 1] - s2[na[j]])) + 1;
lst[i] = j;
}
}
}
//cout << i << " " << Dopi[i] << "\n";
}*/
//cout << idx << "\n";
cdq(0, idx);
vector<int> pos;
int id = idx;
pos.emplace_back(id);
while (lst[id] != id)
{
id = lst[id];
pos.emplace_back(id);
}
reverse(pos.begin(), pos.end());
for (auto& i : pos)
{
if (i != 0 && i != idx)
{
isp[rrp[i]] = 1;
}
}
//for (auto& i : pos)
//{
// cout << i << " ";
//}
//cout << "\n";
//cout << "\n";
int lstone = 0;
int c = 0;
//cout << (pos.size() >= 3 ? pos[1] : 1) << " " << (pos.size() >= 3 ? pos[pos.size() - 2] : n) << "\n";
int now = idx;
while (now)
{
int l = rrp[lst[now]], r = rrp[now];
lstone = a[l];
for (int j = l; j <= r; j++)
{
if (ra[a[j]] != -1) continue;
auto it = st.upper_bound(lstone);
if (it != st.end())
{
fans[j] = ra[*it];
lstone = *it;
st.erase(it);
c++;
}
}
now = lst[now];
}
for (int i = 1; i <= n; i++)
{
if (ra[a[i]] != -1)
{
fans[i] = ra[a[i]];
}
else if (!fans[i])
{
fans[i] = ra[*st.begin()];
st.erase(st.begin());
}
cout << fans[i] << " ";
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现