[BZOJ 5123] matches [Lydsy1712月赛] segment tree

Description

Exam link

Give you an interval \ ([1, n] \ ) of the segment tree, the tree seeking maximum matching and corresponding program number, modulo.

\ (1 \ leq n \ leq 10 ^ {18} \)

Solution

Note \ (f_ {n, 1/ 0} \) representing the interval of length \ (n-\) when the corresponding selected sub-root node of the largest match or not selected, \ (n-G_ {,. 1/0} \) represents a scheme corresponding to the maximum value.

Easy to find the length \ (n-\) state only by the \ (\ left \ lfloor \ frac {n} {2} \ right \ rfloor \) and \ (n- \ left \ lfloor \ frac {n} {2 } \ right \ rfloor \) transfer over.

Then directly open \ (\ text {map} \ ) kept to, the number of states is \ (O (\ log (n )) \) a.

Code

#include <bits/stdc++.h>
#define ll long long
#define CAL(x) cal(f[0][x], f[1][x], g[0][x], g[1][x])
using namespace std;
const int yzh = 998244353;

map<ll, ll> f[2];
map<ll, int> g[2];
ll n;

int cal(ll a, ll b, int c, int d) {
    if (a == b) return (c+d)%yzh;
    return a > b ? c : d;
}
void dp(ll n) {
    if (g[0].count(n)) return;
    ll lx, ly;
    dp(lx = n/2); dp(ly = n-lx);
    
    f[0][n] = max(f[0][lx], f[1][lx])+max(f[0][ly], f[1][ly]);
    g[0][n] = 1ll*CAL(lx)*CAL(ly)%yzh;
    
    if (f[0][lx]+max(f[0][ly], f[1][ly]) >= f[0][ly]+max(f[0][lx], f[1][lx]))
        f[1][n] = f[0][lx]+max(f[0][ly], f[1][ly])+1,
        (g[1][n] += 1ll*g[0][lx]*CAL(ly)%yzh) %= yzh;
    if (f[0][lx]+max(f[0][ly], f[1][ly]) <= f[0][ly]+max(f[0][lx], f[1][lx]))
        f[1][n] = f[0][ly]+max(f[0][lx], f[1][lx])+1,
        (g[1][n] += 1ll*g[0][ly]*CAL(lx)%yzh) %= yzh;
}
int main() {
    scanf("%lld", &n);
    g[0][1] = 1, g[1][1] = 0;
    dp(n);
    if (f[0][n] == f[1][n]) printf("%lld %d\n", f[0][n], (g[0][n]+g[1][n])%yzh);
    else if (f[0][n] > f[1][n]) printf("%lld %d\n", f[0][n], g[0][n]);
    else printf("%lld %d\n", f[1][n], g[1][n]);
    return 0;   
}

Guess you like

Origin www.cnblogs.com/NaVi-Awson/p/11494865.html