• 2019dx#9


    Solved Pro.ID Title Ratio(Accepted / Submitted)
      1001 Rikka with Quicksort 25.85%(38/147)
      1002 Rikka with Cake 31.69%(379/1196)
      1003 Rikka with Mista 5.57%(45/808)
      1004 Rikka with Geometric Sequence 9.52%(2/21)
      1005 Rikka with Game 35.29%(866/2454)
      1006 Rikka with Coin 7.16%(358/5003)
      1007 Rikka with Travels 21.46%(85/396)
      1008 Rikka with Stable Marriage       字典树+贪心 17.02%(8/47)
      1009 Rikka with Traffic Light 0.00%(0/24)
      1010 Rikka with Defensive Line 0.00%(0/20)
      1011 Rikka with Segment Tree 39.39%(13/33)

    1007 Rikka with Travels

    思路:

    一棵树上最长链处理,分出两种情况,一种是(a,b)各占一个端点,还有一种情况a占整条链,b是全踩在非最长链。

    #include <algorithm>
    #include  <iterator>
    #include  <iostream>
    #include   <cstring>
    #include   <cstdlib>
    #include   <iomanip>
    #include    <bitset>
    #include    <cctype>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <stack>
    #include     <cmath>
    #include     <queue>
    #include      <list>
    #include       <map>
    #include       <set>
    #include   <cassert>
    #include <unordered_map>
    // #include<bits/extc++.h>
    // using namespace __gnu_pbds;
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    /**********showtime************/
                const int maxn = 1e5+9;
                int n;
                vector<int>mp[maxn];
                int vis[maxn];
                int dis[maxn];
                vector<int>lian;
                ///扣出最长链
                void koulian() {
                    for(int i=1; i<=n; i++) dis[i] = inf;
                    dis[1] = 0;
                    queue<int>que;  que.push(1);
                    int t = 1;
                    while(!que.empty()) {
                        int u = que.front(); que.pop();
                        if(dis[u] > dis[t])t = u;
                        for(int v : mp[u]) {
                            if(dis[v] > dis[u] + 1) {
                                dis[v] = dis[u] + 1;
                                que.push(v);
                            }
                        }
                    }
    
                    for(int i=1; i<=n; i++) dis[i] = inf;
                    dis[t] = 0;
                    que.push(t);
                    int s = t;
                    while(!que.empty()) {
                        int u = que.front(); que.pop();
                        if(dis[u] > dis[s])s = u;
                        for(int v:mp[u]) {
                            if(dis[v] > dis[u] + 1) {
                                dis[v] = dis[u] + 1;
                                que.push(v);
                            }
                        }
                    }
                    lian.pb(s);
                    vis[s] = 1;
                    while(s != t) {
                        for(int v : mp[s]) {
                            if(dis[v] +1 == dis[s]) {
                                s = v;
                                lian.pb(s);
                                vis[s] = 1;
                                break;
                            }
                        }
                    }
                }
    
                int dpa[maxn], dpb[maxn][2], pre[maxn];
                int dppre[maxn], dpback[maxn];
                ///求出以最长链上一个点为根节点的不经过最长链的最大深度
                void dfs1(int u, int fa) {
                    dpa[u] = 1;
                    for(int v : mp[u]) {
                        if(v == fa || vis[v]) continue;
                        dfs1(v, u);
                        dpa[u] = max(dpa[u], dpa[v] + 1);
                    }}
                void dfs2(int u, int fa) {
                    dpb[u][0] = dpb[u][1] = 1;
                    ///dpb[0]表示包含根节点的最长链
                    ///dpb[1]表示包含根节点的次长链
                    pre[u] = 1;
                    for(int v : mp[u]) {
                        if(vis[v] || v == fa) continue;
                        dfs2(v, u);
                        pre[u] = max(pre[u], pre[v]);
    
                        if(dpb[u][1] <= dpb[v][0] + 1){
                            dpb[u][1] = dpb[v][0] + 1;
                            if(dpb[u][0] < dpb[u][1]) {
                                swap(dpb[u][0], dpb[u][1]);
                            }
                        }
                    }
                    pre[u] = max(pre[u], dpb[u][0] + dpb[u][1] - 1);
                }
                int hei[maxn];
    int main(){
                int T;  scanf("%d", &T);
                while(T--){
                    scanf("%d", &n);
                    for(int i=1; i<n; i++) {
                        int u, v;
                        scanf("%d%d", &u, &v);
                        mp[u].pb(v);
                        mp[v].pb(u);
                    }
                    for(int i=0; i<=n; i++) vis[i] = 0, hei[i] = 0, pre[i] = 0, dppre[i] = 0,dpback[i] = 0;
    
                    koulian();
                    for(int i=0; i<lian.size(); i++) {
                        int v = lian[i];
                        dfs1(v, v);
                        if(i)dppre[i] =  max(dppre[i-1], dpa[v] + i);
                        else dppre[i] = dpa[v];
                        for(int p : mp[v]) {
                            if(vis[p]) continue;
                            dfs2(p, p);
                            pre[v] = max(pre[v], pre[p]);
                        }
                        pre[v] = max(pre[v], pre[lian[max(0, i-1)]]);
                    }
                    int cc = 0;
                    for(int i=lian.size()-1; i>=0; i--) {
                        if(i == lian.size() - 1) dpback[i] = dpa[lian[i]];
                        else dpback[i] = max(dpback[i+1], dpa[lian[i]] + cc);
                        cc++;
                    }
                    int all = lian.size();
                    hei[all] = pre[lian[all-1]];
                    hei[pre[lian[all-1]]] = all;
    
                    for(int i=lian.size() - 1; i>=1; i--) {
                        int v = lian[i];
                        int a = dppre[i-1];
                        int b = dpback[i];
                        hei[a] = max(hei[a], b);
                        hei[b] = max(hei[b], a);
                    }
                    ll sum = 0;
                    int c = 0;
    
                    for(int i=all; i>=1; i--) {
                        c = max(c, hei[i]);
                        sum = sum + c;
                    }
                    printf("%lld
    ", sum);
                    lian.clear();
                    for(int i=1; i<=n; i++) mp[i].clear();
                }
                return 0;
    }
    /*
    10
    9
    1 2
    2 3
    3 4
    4 5
    5 8
    3 6
    3 7
    7 9
    
    
    14
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    3 8
    3 9
    4 10
    4 11
    11 14
    5 12
    5 13
     = 36
    */
    View Code

    1008 Rikka with Stable Marriage   

    思路:

    就是字典树+贪心,和第五场那个贪心顺序反一下就行了

    // #pragma GCC optimize(2)
    // #pragma GCC optimize(3)
    // #pragma GCC optimize(4)
    #include <algorithm>
    #include  <iterator>
    #include  <iostream>
    #include   <cstring>
    #include   <cstdlib>
    #include   <iomanip>
    #include    <bitset>
    #include    <cctype>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <stack>
    #include     <cmath>
    #include     <queue>
    #include      <list>
    #include       <map>
    #include       <set>
    #include   <cassert>
    // #include<bits/extc++.h>
    // using namespace __gnu_pbds;
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    
    /**********showtime************/
                const int maxn = 1e5+9;
                int a[maxn],b[maxn];
                int tot[2],rt[2];
                int bz[33];
                struct node{
                    int ch[2];
                    int fa;
                    int sz;
                    void init(int f) {
                        ch[0] = ch[1] = 0;
                        fa = f;
                        sz = 0;
                    }
                }tree[2][maxn * 30];
                int shu[35];
    
                void add(int p, int len, int flag) {
                    if(len == 0){
                        tree[flag][p].sz++;
                        return;
                    }
    
                    if(tree[flag][p].ch[shu[len]] == 0)
                    {
                        tree[flag][p].ch[shu[len]] = ++ tot[flag];
                        tree[flag][tot[flag]].init(p);
                    }
                    int nx = tree[flag][p].ch[shu[len]];
                    add(nx, len-1, flag);
                    int lc = tree[flag][p].ch[0];
                    int rc = tree[flag][p].ch[1];
                    tree[flag][p].sz = tree[flag][lc].sz + tree[flag][rc].sz;
                }
                void insert(int val, int flag) {
                    int len = 0;
                    for(int i=0; i<=30; i++) shu[++len] = val % 2, val /= 2;
                    add(rt[flag], 30, flag);
                }
                void display(int rt, int flag) {
                    if(rt == 0) return ;
    //                cout<<tree[flag][rt].sz<<endl;
                    display(tree[flag][rt].ch[0], flag);
                    display(tree[flag][rt].ch[1], flag);
                }
                vector<int>vec;
                void find(int a, int b, int cen, int val) {
                    if(cen == 0) {
                        vec.pb(val);
                        tree[0][a].sz--;
                        tree[1][b].sz--;
                        return;
                    }
                    if(tree[0][tree[0][a].ch[0]].sz && tree[1][ tree[1][b].ch[1]].sz){
                        find(tree[0][a].ch[0], tree[1][b].ch[1], cen-1, val + bz[cen-1]);
                    }
                    else if(tree[0][tree[0][a].ch[1]].sz && tree[1][ tree[1][b].ch[0]].sz){
                        find(tree[0][a].ch[1], tree[1][b].ch[0], cen-1, val + bz[cen-1]);
                    }
                    else if(tree[0][ tree[0][a].ch[0] ].sz && tree[1][ tree[1][b].ch[0]].sz ) {
                        find(tree[0][a].ch[0], tree[1][b].ch[0], cen-1, val);
                    }
                    else if(tree[0][ tree[0][a].ch[1] ].sz && tree[1][ tree[1][b].ch[1]].sz) {
                        find(tree[0][a].ch[1], tree[1][b].ch[1], cen-1, val);
                    }
    
                    tree[0][a].sz = tree[0][tree[0][a].ch[0]].sz + tree[0][tree[0][a].ch[1]].sz;
                    tree[1][b].sz = tree[1][tree[1][b].ch[0]].sz + tree[1][tree[1][b].ch[1]].sz;
    
                }
    int main(){
                int T;  scanf("%d", &T);
                bz[0] = 1;
                for(int i=1; i<=30; i++) bz[i] = 2 * bz[i-1];
                while(T--) {
                    tot[0] = tot[1] = 0;
                    rt[0] = ++tot[0];
                    tree[0][rt[0]].init(0);
                    rt[1] = ++tot[1];
                    tree[1][rt[1]].init(0);
    
                    int n;  scanf("%d", &n);
                    for(int i=1; i<=n; i++) scanf("%d", &a[i]), insert(a[i], 0);
                    for(int i=1; i<=n; i++) scanf("%d", &b[i]), insert(b[i], 1);
    
                    vec.clear();
                    for(int i=1; i<=n; i++) {
                        find(rt[0], rt[1], 30, 0);
                    }
                    ll sum = 0;
                    for(int i=0; i<vec.size(); i++) sum += vec[i];
                    printf("%lld
    ", sum);
                }
                return 0;
    }
    View Code
  • 相关阅读:
    约数的问题
    广度搜索基本逻辑
    奇葩概念
    一枚前端UI组件库 KUI for React
    一枚前端UI组件库 KUI for Vue
    跨域的常见问题和解决方案
    Comet,SSE,WebSocket前后端的实现
    web渐进式应用PWA
    IIS 部署node
    javascript 时间戳
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/11378998.html
Copyright © 2020-2023  润新知