2024牛客暑期多校训练营4

· · 个人记录

LCT

思路:反向考虑,动态维护直径,LCA维护点点距离,集合合并直径更新即可,答案必然是直径端点之一,这样会有一个倍增的内存,会卡常数,更简单的方式是并查集直径合并求解

diamond:

#include<iostream>
#include<queue>
using namespace std;
typedef long long int ll;
#define PII pair<int,int>
#define endl '\n'
const int N = 1e6 + 1;
int n, m;
int dep[N], fa[N][20];
PII dot[N];
int p[N];
struct node {
    int x, y, st;
};
int h[N], e[N * 2], ne[N * 2], idx;

inline void add(int a, int b) {
    e[++idx] = b; ne[idx] = h[a]; h[a] = idx;
}
int LCA(int a, int b) {
    if (dep[a] < dep[b])swap(a, b);
    for (int i = 19; i >= 0; --i) {
        if (dep[fa[a][i]] >= dep[b]) {
            a = fa[a][i];
        }
    }
    if (a == b)return a;
    for (int i = 19; i >= 0; --i) {
        if (fa[a][i] != fa[b][i]) {
            a = fa[a][i];
            b = fa[b][i];
        }
    }
    return fa[a][0];
}
void BFS(int u) {
    queue<int> q;
    q.push({u});
    for (int i = 1; i <= n; i++) {
        dep[i] = 1e7;
    }
    dep[u] = 1;
    dep[0] = 0;
    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        for (int i = h[t]; i; i = ne[i]) {
            int v = e[i];
            if (dep[v] > dep[t] + 1) {
                dep[v] = dep[t] + 1;
                fa[v][0] = t;
                q.push(v);
                for (int i = 1; i <= 19; ++i) {
                    fa[v][i] = fa[fa[v][i - 1]][i - 1];
                }
            }
        }
    }
}
int getdist(int a, int b) {
    return  dep[a] + dep[b] - 2 * (dep[LCA(a, b)]);
}
int find(int x) {
    if (p[x] != x) {
        p[x] = find(p[x]);
    }
    return p[x];
}
void init() {
    for (int i = 1; i <= n ; ++i) {
        p[i] = i;
        h[i] = 0;
        dot[i].first = dot[i].second = i;
    }
    idx = 0;
    for (int i = 0; i <= 2 * n; i ++) {
        e[i] = ne[i] = 0;
    }
}
int a, b, x;
node q[N];
int pa,pb;
void solve() {

      cin >> n;
     //n = 1e6;
    init();

    for (int i = 1; i < n; ++i) {

      //  a = b = 1;
        cin >> a >> b >> x;
      //  a=i;
     //   b=i+1;
     //   x=i;
        // g[a].push_back(b);
        // g[b].push_back(a);
        add(a, b);
        add(b, a);
        q[i] = {a, b, x};

    }
    BFS(1);
    // dfs1(1, 0), dfs2(1, 1);
    auto merge = [&](int a, int b) {
        pa = find(a), pb = find(b);
        p[pa] = pb;
        auto [p1, p2] = dot[pa];
        auto [t1, t2] = dot[pb];
        PII &res = dot[pb];
        if (getdist(t1, t2) < getdist(p1, p2)) res = {p1, p2};
        int dist = getdist(res.first, res.second);
        for (auto &x : {p1, p2})
            for (auto &y : {t1, t2}) {
                int cur_dist = getdist(x, y);
                if (dist < cur_dist) {
                    dist = cur_dist;
                    res = {x, y};
                }
            }
        return getdist(res.first, res.second);
    };
    for (int i = 1; i < n ; ++i) {
        auto &[x, y, st] = q[i];
        merge(x, y);
        pa = find(st);
        auto &[l, r] = dot[pa];
        cout << max(getdist(l, st), getdist(r, st)) << ' ';
    }
    cout << endl;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

Zero

思路:对二项式进行展开,对l前缀和一下,得出答案即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define endl '\n'
const int mod=998244353;
const int N=1e5+7;
int suml[31][N];
int cnt[N];
int inv[N];
int c[31][31];
int pw[N];

void init () {
    for (int i = 0; i < 31; i ++ ) {
        for (int j = 0; j <= i; j ++ ) {
            if (!j) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
}
int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1){
            res=res*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
void  solve() {
    int n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    s=" "+s;
    init();
    // cout<<c[3][2]<<endl;

    pw[0]=inv[0]=1;
    int d= ksm(2,mod-2);
    for (int i = 1; i <=n ; ++i) {
        pw[i]=pw[i-1]*2%mod;
        inv[i]=inv[i-1]*d%mod;

    }
   // cout<<inv[3]<<' ';
    for (int i = 1; i <=n ; ++i) {
        cnt[i]=cnt[i-1];
        if(s[i]=='?')cnt[i]++;
        for (int j = 0; j <=k ; ++j) {
            suml[j][i]=suml[j][i-1];
            if(s[i]!='0'){
                suml[j][i]+=ksm(mod-i,k-j)*pw[cnt[i-1]]%mod;
                suml[j][i]%=mod;
            }
        }
    }
    int ans=0;
    int ls=1;
    for (int r = 1; r <=n ; ++r) {
        if(s[r]=='0'){
            ls=r+1;
        }
        else {
            for (int i = 0; i <= k; ++i) {
                ans +=c[k][i]*ksm(r+1,i)%mod*inv[cnt[r]]%mod*(suml[i][r]-suml[i][ls-1]+mod)%mod;
                ans%=mod;
            }
        }
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0);
    int t=1;
    //   cin>>t;
    while (t--){
        solve();
    }
}