Delicious Problem: AT_arc228_b
FantasySegmentTree · · 题解
标有 Delicious Problem 标号的题目将有 Hint 题解。这种题目适合一步步品尝。
:::info[Hint 1]
如果没有字典序的要求,那么对于给定的序列,你能否给出一个构造
:::success[Answer 1] 这当然可以了。
首先根节点不用说。对于每个非根节点
:::
:::info[Hint 2] 考虑一下,如果加入了字典序的要求,会有什么变化? :::
:::success[Answer 2]
设当前遍历到
| 于是 |
|---|
:::info[Hint 3] 怎么把前两个 Hint 提供的信息结合起来? :::
:::success[Answer 3]
你会发现
:::success[Code]
#include <iostream>
#define N 200005
using namespace std;
typedef long long ll;
ll n, p[N], a[N], c[N], top;
ll st[N];
struct node {
ll l, r, minn, mink;
}b[N << 2];
void push_up(ll x) {
b[x].minn = min(b[x << 1].minn, b[x << 1 | 1].minn);
if(b[x << 1].minn < b[x << 1 | 1].minn) b[x].mink = b[x << 1].mink;
else b[x].mink = b[x << 1 | 1].mink;
}
void build(ll l, ll r, ll x) {
b[x].l = l, b[x].r = r;
if(l == r) {
b[x].minn = a[p[l]];
b[x].mink = l;
return;
}
ll mid = (l + r) >> 1;
build(l, mid, x << 1);
build(mid + 1, r, x << 1 | 1);
push_up(x);
}
void change(ll id, ll k, ll x) {
if(b[x].l > id || b[x].r < id) return;
if(b[x].l == b[x].r) {
b[x].minn = k;
return;
}
change(id, k, x << 1);
change(id, k, x << 1 | 1);
push_up(x);
}
pair <int, int> query(ll l, ll r, ll x) {
if(b[x].l >= l && b[x].r <= r) return make_pair(b[x].minn, b[x].mink);
ll mid = (b[x].l + b[x].r) >> 1;
if(r <= mid) return query(l, r, x << 1);
else if(l > mid) return query(l, r, x << 1 | 1);
else {
pair <int, int> lx = query(l, r, x << 1), rx = query(l, r, x << 1 | 1), nx;
nx.first = min(lx.first, rx.first);
if(lx.first < rx.first) nx.second = lx.second;
else nx.second = rx.second;
return nx;
}
}
int main() {
cin >> n;
for(ll i = 1; i <= n; i++) cin >> p[i];
for(ll i = 1; i <= n; i++) cin >> a[i];
build(1, n, 1);
st[++top] = 1;
ll ans = 0;
for(ll i = 2; i <= n; i++) {
ll cs = 1;
while(top && p[st[top]] < p[i]) top--;
if(top) cs = st[top];
st[++top] = i;
pair <int, int> sr = query(cs, i - 1, 1);
ans += sr.first;
ll t = sr.second;
c[p[t]]++;
change(t, a[p[t]] * (2 * c[p[t]] + 1), 1);
}
cout << ans;
}
:::