xyd 模拟赛二·题解
Ling_zeroo · · 个人记录
T1 排列
显然对于一行只能选一个点,对于第一行只能选第
然后呢?不会了。打个表!
盯着表可以注意到,如果把第
实际上,一个序列可以被分成若干个子序列的子问题。对于一个三个数
然后就做完了,跑个 DP,记
时间复杂度
T2 onepointfive
我要是当时会四边形不等式我就会完了
发现
扩展到树上,考虑 dsu on tree。对于一条重链维护一个单调队列。处理一个点时,先遍历轻子树,通过当前的队列暴力更新轻子树内的答案,不加入队列;再遍历重儿子,加入队列;再遍历轻儿子,开一个新队列维护。维护队列时使用类似双指针的东西维护一个当前可能作为决策点的区间
时间复杂度
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define lb long double
#define i128 __int128
#define ull unsigned long long
#define pii pair<ll, ll>
#define fir first
#define sec second
#define iinf (int)(2e9)
#define linf (ll)(1e18)
#define rep(i, l, r) for(int i = l; i <= r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)
ll read(){
ll x = 0, f = 1; char ch = getchar();
while(!isdigit(ch)){if(ch == '-')f = -1; ch = getchar();}
while(isdigit(ch)){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
return x * f;
}
const int maxn = 1e6 + 5;
int n, a[maxn];
vector<int> G[maxn];
int dep[maxn], son[maxn], siz[maxn];
void init(int u, int ff) {
dep[u] = dep[ff] + 1, siz[u] = 1;
for(auto v : G[u]) {
init(v, u); siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
db f[maxn], val[maxn];
struct Seg{int l, r, x; db y;} stk[maxn];
db w(int x, db y){return pow(x, 1.5) + y;}
void dfs2(int u, int l, int r){
while(l <= r && stk[l].r < dep[u]) ++l;
assert(l <= r);
f[u] = min(f[u], w(dep[u] - stk[l].x, stk[l].y) + a[u]);
for(auto v : G[u]){
dfs2(v, l, r);
}
}
void dfs1(int u, int l, int r){
while(l <= r && stk[l].r < dep[u]) ++l;
if(l <= r) {
f[u] = min(f[u], w(dep[u] - stk[l].x, stk[l].y) + a[u]);
stk[l].l = dep[u] + 1;
}
while(l <= r && w(stk[r].l - stk[r].x, stk[r].y) > w(stk[r].l - dep[u], f[u])) --r;
int pos = dep[u] + 1;
if(l <= r){
pos = stk[r].r + 1;
int L = stk[r].l, R = stk[r].r, mid;
while(L <= R){
mid = (L + R) >> 1;
if(w(mid - stk[r].x, stk[r].y) > w(mid - dep[u], f[u])) pos = mid, R = mid - 1;
else L = mid + 1;
}
stk[r].r = pos - 1;
}
if(pos <= n) stk[++r] = {pos, n, dep[u], f[u]};
for(auto v : G[u]){
if(v == son[u]) continue;
dfs2(v, l, r);
}
if(son[u]) dfs1(son[u], l, r);
for(auto v : G[u]){
if(v == son[u]) continue;
dfs1(v, 1, 0);
}
}
void sol(){
n = read();
for(int i = 1; i <= n; i++) val[i] = sqrt(i) * i;
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 2; i <= n; i++){
int ff = read(); G[ff].push_back(i);
}
init(1, 0);
for(int i = 0; i <= n; i++) f[i] = 1e30;
f[1] = 0;
dfs1(1, 1, 0);
for(int i = 1; i <= n; i++) printf("%.4f ", f[i]);
}
int main(){
freopen("onepointfive.in", "r", stdin);
freopen("onepointfive.out", "w", stdout);
int _ = 1;
while(_--) sol();
}
T3 Interesting DS Problem
暂时不会。