Submission #1108050

#TimeUsernameProblemLanguageResultExecution timeMemory
1108050matuCat in a tree (BOI17_catinatree)C++17
100 / 100
562 ms487492 KiB
#include <bits/stdc++.h>
// #include <tr2/dynamic_bitset>
 
using namespace std;
// using namespace tr2;
#pragma GCC optimize("O3,unroll-loops,Ofast")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
const long double eps = 1e-9;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int randgen(int left, int right) {
    return uniform_int_distribution<int>(left, right)(rng);
}
long long randgenll(long long left, long long right) {
    return uniform_int_distribution<long long>(left, right)(rng);
}
 
typedef long long ll;
typedef long double ld;
const int mod = 1e9 + 7;
struct Mint
{
    int val;
    Mint(int x = 0)
    {
        val = x % mod;
    }
    Mint(long long x)
    {
        val = x % mod;
    }
    Mint operator+(Mint oth)
    {
        return val + oth.val;
    }
    Mint operator*(Mint oth)
    {
        return 1LL * val * oth.val;
    }
    Mint operator-(Mint oth)
    {
        return val - oth.val + mod;
    }
    Mint fp(Mint a, long long n){
        Mint p = 1;
        while(n){
            if(n & 1){
                p = p * a;
            }
            a = a * a;
            n /= 2;
        }
        return p;
    }
    Mint operator/(Mint oth){
        Mint invers = fp(oth, mod - 2);
        return 1LL * val * invers.val;
    }
    friend ostream& operator << (ostream& os, const Mint& lol){
        os << lol.val;
        return os;
    }
};
 
struct AINT{
    vector<pair<ll,Mint>> aint;
    vector<pair<ll,Mint>> lazy;
    pair<ll,Mint> b;
    AINT(int n){
        b = {1e18,Mint(0)};
        aint.assign(n * 4 + 1,make_pair(1e18,Mint(0)));
        lazy.assign(n * 4 + 1, make_pair(1e18, Mint(0)));
    }
    void update(int v, int tl, int tr, int l, int r, pair<ll,Mint> val){
        if(lazy[v].first != 1e18){
            if(aint[v].first == lazy[v].first){
                aint[v].second = aint[v].second + lazy[v].second;
            }else if(aint[v].first > lazy[v].first) aint[v] = lazy[v];
 
            if(tl != tr){
                if(lazy[v * 2].first == lazy[v].first){
                    lazy[v * 2].second = lazy[v *  2].second + lazy[v].second;
                }else if(lazy[v * 2].first > lazy[v].first) lazy[v * 2] = lazy[v];
                
 
                if(lazy[v * 2 + 1].first == lazy[v].first){
                    lazy[v * 2 + 1].second = lazy[v * 2 + 1].second + lazy[v].second;
                }else if(lazy[v * 2 + 1].first > lazy[v].first){
                    lazy[v * 2 + 1] = lazy[v];
                }
            }
            lazy[v] = b;
        }
        if(l <= tl && r >= tr){
            if(aint[v].first == val.first){
                aint[v].second = aint[v].second + val.second;
            }else if(aint[v].first > val.first){
                    aint[v] = val;
            }
 
            if(tl != tr){
                if(lazy[v * 2].first == val.first){
                    lazy[v * 2].second = lazy[v *  2].second + val.second;
                }else if(lazy[v * 2].first > val.first){
                    lazy[v * 2] = val;
                }
                
 
                if(lazy[v * 2 + 1].first == val.first){
                    lazy[v * 2 + 1].second = lazy[v * 2 + 1].second + val.second;
                }else if(lazy[v * 2 + 1].first > val.first){
                    lazy[v * 2 + 1] = val;
                }
            }
            return;
        }
        if(l > tr || r < tl) return;
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l,r , val);
        update(v * 2 + 1, tm + 1, tr, l, r, val);
        
        if(aint[v * 2].first == aint[v * 2 + 1].first){
            aint[v] = aint[v * 2];
            aint[v].second = aint[v].second + aint[v * 2 + 1].second;
        }else{
            if(aint[v * 2].first < aint[v * 2 + 1].first) aint[v] = aint[v * 2];
            else aint[v] = aint[v * 2 + 1];
        }
 
 
    }
    pair<ll,Mint> query(int v, int tl, int tr, int l, int r){
        if(lazy[v].first != 1e18){
            if(aint[v].first == lazy[v].first){
                aint[v].second = aint[v].second + lazy[v].second;
            }else if(aint[v].first > lazy[v].first) aint[v] = lazy[v];
 
            if(tl != tr){
                if(lazy[v * 2].first == lazy[v].first){
                    lazy[v * 2].second = lazy[v *  2].second + lazy[v].second;
                }else if(lazy[v * 2].first > lazy[v].first) lazy[v * 2] = lazy[v];
                
 
                if(lazy[v * 2 + 1].first == lazy[v].first){
                    lazy[v * 2 + 1].second = lazy[v * 2 + 1].second + lazy[v].second;
                }else if(lazy[v * 2 + 1].first > lazy[v].first){
                    lazy[v * 2 + 1] = lazy[v];
                }
            }
            lazy[v] = b;
        }
        if(l <= tl && r >= tr) return aint[v];
        if(l > tr || r < tl) return make_pair(1e18,Mint(0));
        int tm = (tl + tr) / 2;
        pair<ll,Mint> p1 = query(v * 2, tl ,tm, l, r);
        pair<ll,Mint> p2 = query(v * 2 + 1, tm + 1, tr, l,r);
        if(p1.first == p2.first){
            p1.second = p1.second + p2.second;
            return p1;
        }else if(p1.first < p2.first) return p1;
        return p2;
 
        // int tm = (tl + tr) / 2;
        // if(l <= tl && r >= tr) return aint[v];
        // if(l > tr || r < tl) return 0;
        // return max(query(v * 2, tl, tm,l,r), query(v * 2 + 1, tm + 1, tr, l,r));
        
    }
};
struct AIB{
    vector<int> aib;
    AIB(int n){
        aib.assign(n + 1,0);
    
    }
    void update(int pos, int val){
        for(; pos < aib.size(); pos += (pos & -pos)){
            aib[pos] += val;
        }
    }
    int query(int pos){
        int pl = 0;
   
        for(; pos > 0; pos -= (pos & -pos)) pl += aib[pos];
        return pl;
    }
};
 
int red = 0;
 
int ______________________________________________________________________________________________________________________________________________;
 
void solve(){
    int n, d;
    cin >> n >> d;
    vector<vector<int>> liste(n + 1);
    vector<deque<int>> dp(n + 1),maxp(n + 1);
    
    for(int i = 2; i <= n; i++){
        int x;
        cin >> x;
        x++;
        liste[i].push_back(x);
        liste[x].push_back(i);
    }
    int ans = 0;
    function<void(int,int)> dfs = [&](int nod, int p){
        int maxim = 0, nd = 0;
        for(auto i : liste[nod]){
            if(i == p) continue;
            dfs(i,nod);
            if(maxim < dp[i].size()){
                maxim = dp[i].size();
                nd = i;
            }
        }
 
        if(liste[nod].size() == 1 && nod != 1){
            dp[nod].push_back(1);
            maxp[nod].push_back(1);
            return;
        }
        
        int crt = max(1, 1 + (dp[nd].size() <= d - 1 ? 0 : maxp[nd][d - 1]));
        swap(dp[nod],dp[nd]);
        swap(maxp[nd],maxp[nod]);
 
        
        dp[nod].push_front(crt);
        int lvl = maxp[nod][0];
        maxp[nod].push_front(max(crt,lvl));
 
        
        for(auto i : liste[nod]){
            if(i == p || i == nd) continue;
            int crt = max(1, 1 + (dp[i].size() <= d - 1 ? 0 : maxp[i][d - 1]));
            dp[i].push_front(crt);
            int lvl = maxp[i][0];
            maxp[i].push_front(max(crt,lvl));
            // if(nod == 1 && i == 3){
            //     for(auto j : dp[i]){
            //         cout << j << " ";
            //     }
            // }
            for(int j = 0; j < dp[i].size(); j++){
                int pos = max(j, d - j);
                int val1 = dp[i][j] + (dp[nod].size() <= pos ? 0 : maxp[nod][pos]);
                int val2 = dp[nod][j] + (dp[i].size() <= pos ? 0 : maxp[i][pos]);
                // if(nod == 1 && i == 3 && j == 1){
                //     cout << val1 << " " << val2;
                //     //cout << maxp[nod].size();
                // }
                dp[nod][j] = max({dp[nod][j],val1,val2, dp[i][j]});
 
            }
            for(int j = dp[i].size() - 1; j >= 0; j--){
                if(j + 1 < dp[nod].size()){
                    maxp[nod][j] = max(dp[nod][j], maxp[nod][j + 1]);
                }else{
                    maxp[nod][j] = dp[nod][j];
                }
            }
        }
        ans = max(ans, maxp[nod][0]);
    };
 
    dfs(1,1);
    cout << ans;
}
int32_t main(){
    cin.tie(0)->sync_with_stdio(0);
    
    int t = 1; 
    if(red) cin >> t;
   
    while(t--){
        solve();
    }
 
 
}
 
 
/*
 4 1
0 0 1
 
 
j + 1 + p >= d
p >= d - j - 1
 
i + j >= d
 
j >= d - i;
*/

Compilation message (stderr)

catinatree.cpp: In member function 'void AIB::update(int, int)':
catinatree.cpp:176:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  176 |         for(; pos < aib.size(); pos += (pos & -pos)){
      |               ~~~~^~~~~~~~~~~~
catinatree.cpp: In lambda function:
catinatree.cpp:211:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::deque<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  211 |             if(maxim < dp[i].size()){
      |                ~~~~~~^~~~~~~~~~~~~~
catinatree.cpp:223:45: warning: comparison of integer expressions of different signedness: 'std::deque<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  223 |         int crt = max(1, 1 + (dp[nd].size() <= d - 1 ? 0 : maxp[nd][d - 1]));
      |                               ~~~~~~~~~~~~~~^~~~~~~~
catinatree.cpp:235:48: warning: comparison of integer expressions of different signedness: 'std::deque<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  235 |             int crt = max(1, 1 + (dp[i].size() <= d - 1 ? 0 : maxp[i][d - 1]));
      |                                   ~~~~~~~~~~~~~^~~~~~~~
catinatree.cpp:244:30: warning: comparison of integer expressions of different signedness: 'int' and 'std::deque<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  244 |             for(int j = 0; j < dp[i].size(); j++){
      |                            ~~^~~~~~~~~~~~~~
catinatree.cpp:246:55: warning: comparison of integer expressions of different signedness: 'std::deque<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  246 |                 int val1 = dp[i][j] + (dp[nod].size() <= pos ? 0 : maxp[nod][pos]);
      |                                        ~~~~~~~~~~~~~~~^~~~~~
catinatree.cpp:247:55: warning: comparison of integer expressions of different signedness: 'std::deque<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  247 |                 int val2 = dp[nod][j] + (dp[i].size() <= pos ? 0 : maxp[i][pos]);
      |                                          ~~~~~~~~~~~~~^~~~~~
catinatree.cpp:256:26: warning: comparison of integer expressions of different signedness: 'int' and 'std::deque<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  256 |                 if(j + 1 < dp[nod].size()){
      |                    ~~~~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...