zoukankan      html  css  js  c++  java
  • 2019 ICPC Asia Xuzhou Regional

    2019 ICPC Asia Xuzhou Regional

    题号 标题 通过率 我的状态
    A Cat题库链接 240/893 通过
    B Cats line up 题库链接 2/6 未通过
    C ❤️ numbers 题库链接 287/803 通过
    D Polycut 题库链接 0/8 未通过
    E Multiply 题库链接 69/362 通过
    F The Answer to the Ultimate Question of Life, The Universe, and Everything. 题库链接 243/801 通过
    G Factory 题库链接 0/1 未通过
    H Yuuki and a problem 题库链接 22/127 通过
    I Interesting game 题库链接 5/20 未通过
    J Loli, Yen-Jen, and a graph problem 题库链接 20/83 未通过
    K K-rectangle 题库链接 1/5 未通过
    L Loli, Yen-Jen, and a cool problem 题库链接 18/90 通过
    M M. Kill the tree 题库链接 67/584 通过

    A - Cat

    计蒜客 - 42540

    每四个组成一组,然后左右端点枚举一下即可(代码写的有点搓)

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    int T;
    ll l, r, s;
    int main() {
        cin >> T;
        while(T--){
            scanf("%lld%lld%lld", &l, &r, &s);
            if(r - l + 1 <= 4){
                ll res = 0, cur = 0;
                for (ll i = l; i<=r;i++){
                    cur = 0;
                    for (ll j = i; j <= r;j++){
                        cur ^= j;
                        if(cur <= s)
                            res = max(res, j - i + 1);
                    }
                }
                printf("%lld
    ", res ? res : -1);
                continue;
            }
            ll res = 0;
            if(l % 2 == 0){
                ll nr = (r - l + 1) / 4 * 4 + l;
                ll cur = 0;
                for (ll j = nr; j <= r; j++) {
                    cur ^= j;
                    if(cur <= s)
                        res = max(res, j - nr + 1);
                }
                res += nr - l;
            }
            if(l % 2 == 1){
                ll nl = l + 1;
                ll nr = (r - nl + 1) / 4 * 4 + nl;
                ll cur = 0;
                for (ll j = nr; j <= r;j++){
                    cur ^= j;
                    if(cur <= s)
                        res = max(res, j - nr + 1);
                }
                cur = l;
                if(cur <= s)
                    res = max(res, 1ll);
                for (ll j = nr; j <= r;j++){
                    cur ^= j;
                    if(cur <= s)
                        res = max(res, j - nr + 2);
                }
                res += nr - nl;
            }
            printf("%lld
    ", res);
        }
        return 0;
    }
    

    C - ❤️ numbers

    计蒜客 - 42542

    当区间长度特别长时,素数个数是非常少的,参考:https://baike.baidu.com/item/%E7%B4%A0%E6%95%B0%E5%88%86%E5%B8%83/369166

    所以大区间直接输出Yes,小区间暴力判断即可。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int N = 100000 + 5;
    
    int T, l, r;
    bool prime(int x){
        if(x == 1 || x == 2)
            return true;
        for (int i = 2; i <= x / i;i++){
            if(x % i == 0)
                return false;
        }
        return true;
    }
    bool check(int l,int r){
        int num = 0;
        for (int i = l; i <= r;i++){
            if(prime(i))
                num++;
        }
        if(3 * num < r - l + 1)
            return true;
        else
            return false;
    }
    int main() {
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &l, &r);
            if(r - l + 1 >= 50){
                puts("Yes");
            }else{
                puts(check(l, r) ? "Yes" : "No");
            }
        }
        return 0;
    }
    

    E - Multiply

    计蒜客 - 42544

    (Z = a_1! imes a_2! imes cdots imes a_n!)

    找最大的 (i) 使得 (Z imes X^i)(Y!) 的因子,首先求出 (X!) 的所有质因数和其指数,然后遍历这些质因数,对于所有(a_i!),以及(Y!),求出其对(X) 的指数的贡献,取所有质因数里面最小的那个即可。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <unordered_map>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    /*
    Miller_Rabin 算法进行素数测试
    速度快可以判断一个 < 2^63 的数是不是素数
    */
    const int S = 8;
    typedef long long ll;
    //计算 res = (a*b)%c
    ll mult_mod(ll a, ll b, ll c){
        a %= c;
        b %= c;
        ll res = 0;
        ll tmp = a;
        for (; b;b>>=1){
            if(b & 1) {
                res += tmp;
                if(res > c)
                    res -= c;
            }
            tmp <<= 1;
            if(tmp > c)
                tmp -= c;
        }
        return res;
    }
    ll pow_mod(ll a,ll b, ll mod){
        ll res = 1;
        a %= mod;
        for (; b;b>>=1){
            if(b & 1)
                res = mult_mod(res, a, mod);
            a = mult_mod(a, a, mod);
        }
        return res;
    }
    /*
    通过 a^(n-1)=1(mod n)来判断 n 是不是素数
    n - 1 = x * 2^t 中间使用二次判断
    是合数返回true,不一定是合数返回false
    */
    bool check(ll a,ll n,ll x,ll t){
        ll res = pow_mod(a, x, n);
        ll last = res;
        for (int i = 1; i <= t;i++){
            res = mult_mod(res, res, n);
            if(res == 1 && last != 1 && last != n-1)
                return true;
            last = res;
        }
        if(res != 1)
            return true;
        return false;
    }
    /*
    Miller_Rabin 算法
    是素数返回true
    不是素数返回false
    */
    bool Miller_Rabin(ll n){
        if(n < 2)
            return false;
        if(n == 2)
            return true;
        if((n&1) == 0)
            return false;
        ll x = n - 1;
        ll t = 0;
        while((x & 1) == 0) {
            x >>= 1, t++;
        }
        for (int i = 0; i < S;i++){
            ll a = rand() % (n - 1) + 1;
            if(check(a,n,x,t))
                return false;
        }
        return true;
    }
    /*
    Pollard_rho 算法进行质因数分解
    */
    ll fac[100];
    int tol;
    ll gcd(ll a,ll b){
        ll t;
        while(b){
            t = a;
            a = b;
            b = t % b;
        }
        if(a >= 0)
            return a;
        else
            return -a;
    }
    //找出一个因子
    ll pollard_rho(ll x,ll c){
        ll i = 1, k = 2;
        ll x0 = rand() % (x - 1) + 1;
        ll y = x0;
        while(1){
            i++;
            x0 = (mult_mod(x0, x0, x) + c) % x;
            ll d = gcd(y - x0, x);
            if(d != 1 && d != x)
                return d;
            if(y == x0)
                return x;
            if(i == k) {
                y = x0;
                k += k;
            }
        }
    }
    //对 n 进行质因数分解,存入factor,k设置为107左右
    void findfac(ll n,int k){
        if(n == 1)
            return;
        if(Miller_Rabin(n)){
            fac[tol++] = n;
            return;
        }
        ll p = n;
        int c = k;
        while(p >= n)
            p = pollard_rho(p, c--);
        findfac(p, k);
        findfac(n / p, k);
    }
    //POJ 1811
    // 给出一个N,如果是素数输出Prime,否则输出最小的素因子
    ll a[100010];
    int main(){
        int T;
        ll n,x,y;
        scanf("%d", &T);
        while(T--){
            tol = 0;
            scanf("%lld%lld%lld", &n, &x, &y);
            for (int i = 1; i <= n;i++){
                scanf("%lld", &a[i]);
            }
            ll res = 1ll << 60;
            findfac(x, 127);
            for (int i = 0; i < tol;i++){
                ll now = 0;
                while(x % fac[i] == 0){
                    now++;
                    x /= fac[i];
                }
                if(now == 0) continue;
                ll nu = 0, tp, w;
                //cout << fac[i] << endl;
                for (int j = 1; j <= n;j++){
                    tp = log(a[j]) / log(fac[i]);
                    w = 1;
                    for (int k = 1; k <= tp;k++)
                        w *= fac[i], nu -= a[j] / w;
                }
                w = 1;
                tp = log(y) / log(fac[i]);
                for (int k = 1; k <= tp;k++)
                    w *= fac[i], nu += y / w;
                
                res = min(res, nu/now);
            }
            printf("%lld
    ", res);
        }
    }
    

    F - The Answer to the Ultimate Question of Life, The Universe, and Everything.

    计蒜客 - 42545

    (a^3+b^3+c^3=x) 已知 (y=x^3) 在实数域上严格单调递增,所以枚举一个a,然后枚举一个b,根据确定的x求出c,然后再根据c的值对b进行调整(双指针),可以预处理出来合法的(a^3+b^3+c^3=x) ,复杂度是(O(n*5000^2)) ,打表出来直接输出即可。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <unordered_map>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int N = 5000 + 5;
    
    struct node{
        int a, b, c;
    } a[201];
    bool b[201];
    void init(){
        a[0] = {5000,0,-5000};
        a[1] = {5000,1,-5000};
        a[2] = {4375,-486,-4373};
        a[3] = {4,4,-5};
        b[4] = 1;
        b[5] = 1;
        a[6] = {644,-205,-637};
        a[7] = {168,44,-169};
        a[8] = {5000,2,-5000};
        a[9] = {217,-52,-216};
        a[10] = {683,-353,-650};
        a[11] = {843,-641,-695};
        a[12] = {10,7,-11};
        b[13] = 1;
        b[14] = 1;
        a[15] = {332,-262,-265};
        a[16] = {4118,-588,-4114};
        a[17] = {2977,2195,-3331};
        a[18] = {1671,-1276,-1373};
        a[19] = {91,47,-95};
        a[20] = {2833,-741,-2816};
        a[21] = {445,-287,-401};
        b[22] = 1;
        b[23] = 1;
        a[24] = {8,8,-10};
        a[25] = {2357,1839,-2683};
        a[26] = {2106,237,-2107};
        a[27] = {5000,3,-5000};
        a[28] = {2269,-249,-2268};
        a[29] = {235,-69,-233};
        b[30] = 1;
        b[31] = 1;
        b[32] = 1;
        b[33] = 1;
        a[34] = {1557,-244,-1555};
        a[35] = {1154,-509,-1120};
        a[36] = {2731,2358,-3223};
        a[37] = {445,-84,-444};
        a[38] = {25,16,-27};
        b[39] = 1;
        b[40] = 1;
        b[41] = 1;
        b[42] = 1;
        a[43] = {837,-307,-823};
        a[44] = {8,-5,-7};
        a[45] = {2025,1709,-2369};
        a[46] = {815,-473,-758};
        a[47] = {139,49,-141};
        a[48] = {3991,-1247,-3950};
        b[49] = 1;
        b[50] = 1;
        a[51] = {659,602,-796};
        b[52] = 1;
        a[53] = {2141,1518,-2370};
        a[54] = {3891,-648,-3885};
        a[55] = {3131,1837,-3329};
        a[56] = {559,505,-672};
        a[57] = {982,361,-998};
        b[58] = 1;
        b[59] = 1;
        a[60] = {1202,-163,-1201};
        a[61] = {845,668,-966};
        a[62] = {2903,-1561,-2744};
        a[63] = {146,102,-161};
        a[64] = {5000,4,-5000};
        a[65] = {903,403,-929};
        a[66] = {4,1,1};
        b[67] = 1;
        b[68] = 1;
        a[69] = {398,134,-403};
        a[70] = {2325,824,-2359};
        a[71] = {443,401,-533};
        a[72] = {434,-104,-432};
        a[73] = {344,-146,-335};
        b[74] = 1;
        b[75] = 1;
        b[76] = 1;
        b[77] = 1;
        a[78] = {2123,-829,-2080};
        a[79] = {711,-196,-706};
        a[80] = {1366,-706,-1300};
        a[81] = {2638,-1719,-2368};
        a[82] = {1188,847,-1317};
        a[83] = {3651,1315,-3707};
        b[84] = 1;
        b[85] = 1;
        b[86] = 1;
        a[87] = {4271,-1972,-4126};
        a[88] = {1686,-1282,-1390};
        a[89] = {2036,1953,-2514};
        a[90] = {1798,365,-1803};
        a[91] = {3992,-2912,-3389};
        a[92] = {4039,861,-4052};
        a[93] = {253,-98,-248};
        b[94] = 1;
        b[95] = 1;
        a[96] = {20,14,-22};
        a[97] = {3200,-991,-3168};
        a[98] = {2391,-1638,-2101};
        a[99] = {984,-622,-893};
        a[100] = {1870,-903,-1797};
        a[101] = {2325,319,-2327};
        a[102] = {229,118,-239};
        b[103] = 1;
        b[104] = 1;
        a[105] = {8,-4,-7};
        a[106] = {2760,-1165,-2689};
        a[107] = {1117,947,-1309};
        a[108] = {1345,-948,-1165};
        a[109] = {2924,853,-2948};
        b[110] = 1;
        a[111] = {4966,-2312,-4793};
        b[112] = 1;
        b[113] = 1;
        b[114] = 1;
        a[115] = {11,8,-12};
        a[116] = {1945,-757,-1906};
        a[117] = {962,-555,-896};
        a[118] = {4327,383,-4328};
        a[119] = {3789,-1673,-3677};
        a[120] = {2725,1219,-2804};
        b[121] = 1;
        b[122] = 1;
        a[123] = {38,-16,-37};
        a[124] = {5,0,-1};
        a[125] = {5000,5,-5000};
        a[126] = {2217,-419,-2212};
        a[127] = {4988,-3881,-4034};
        a[128] = {3997,-726,-3989};
        a[129] = {1801,-1238,-1580};
        b[130] = 1;
        b[131] = 1;
        a[132] = {5,2,-1};
        a[133] = {389,167,-399};
        a[134] = {3203,-1766,-3013};
        a[135] = {1395,-629,-1351};
        a[136] = {946,816,-1116};
        a[137] = {801,-428,-758};
        a[138] = {103,-77,-86};
        b[139] = 1;
        b[140] = 1;
        a[141] = {116,104,-139};
        a[142] = {8,-3,-7};
        b[143] = 1;
        a[144] = {3342,-2552,-2746};
        a[145] = {10,-7,-8};
        a[146] = {376,-263,-327};
        a[147] = {2131,1528,-2366};
        b[148] = 1;
        b[149] = 1;
        a[150] = {317,260,-367};
        a[151] = {447,215,-463};
        a[152] = {741,486,-805};
        a[153] = {3744,-695,-3736};
        a[154] = {2145,-516,-2135};
        a[155] = {3721,-1049,-3693};
        b[156] = 1;
        b[157] = 1;
        b[158] = 1;
        a[159] = {1526,383,-1534};
        a[160] = {3972,-1654,-3874};
        a[161] = {4980,-2476,-4767};
        a[162] = {4180,-1417,-4125};
        a[163] = {4033,-2943,-3423};
        a[164] = {79,-59,-66};
        b[165] = 1;
        b[166] = 1;
        b[167] = 1;
        a[168] = {890,-574,-802};
        a[169] = {1521,-1012,-1354};
        a[170] = {4047,-2149,-3834};
        a[171] = {1178,891,-1328};
        b[172] = 1;
        b[173] = 1;
        a[174] = {349,-170,-335};
        b[175] = 1;
        b[176] = 1;
        a[177] = {1169,-160,-1168};
        a[178] = {15,-10,-13};
        a[179] = {2691,1503,-2839};
        b[180] = 1;
        a[181] = {4861,974,-4874};
        a[182] = {91,-29,-90};
        a[183] = {4876,976,-4889};
        b[184] = 1;
        b[185] = 1;
        a[186] = {5,5,-4};
        a[187] = {2000,-1092,-1885};
        a[188] = {1635,318,-1639};
        a[189] = {1974,-1403,-1702};
        a[190] = {4815,-593,-4812};
        a[191] = {399,-215,-377};
        a[192] = {16,16,-20};
        b[193] = 1;
        b[194] = 1;
        b[195] = 1;
        a[196] = {1112,-579,-1057};
        a[197] = {3026,-1606,-2867};
        a[198] = {3809,-1347,-3752};
        a[199] = {2199,508,-2208};
        a[200] = {2334,-638,-2318};
    }
    int main() {
        int T, x;
        cin >> T;
        init();
        while(T--){
            cin >> x;
            if(b[x])
                printf("impossible
    ");
            else
                printf("%d %d %d
    ", a[x].a, a[x].b, a[x].c);
        }
        return 0;
    }
    

    H - Yuuki and a problem

    计蒜客 - 42547

    问题关键如何快速求一个集合中可以组成的数字集的mex。

    首先考虑区间中数字范围在[1,1] 中的和 sum,

    若 sum = 0, 则 答案为1, 否则可以组成[1,sum] 中的任意一个数字。

    然后考虑区间中数字在[1, sum+1] 中的和 nsum,这表示可以组成[1.nsum] 中的任意一个数字,因为[1,1]就可以组成了[1,sum],如果再多一个数字 x ,那么就可以组成[x,x+sum] ,我们只有在[2, sum+1]中找到这样的x,也就是说nsum != sum, 才能使得 sum+1 可以被组成,否则 sum+1 就是第一个无法组成的数字。

    然后我们令sum = nsum,继续查询[1, sum+1] 中数字的和即可。

    sum的增长速度应该是超过了斐波那契,所以查询次数很少。待修改的查询区间内[l,r]中的数字和,可以用树状数组维护权值线段树

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int N = 200000 + 5;
    int n, m, q, a[N], L[30][30], R[30][30], cl, cr;
    inline int lowbit(int x) { return x & -x; }
    struct Seg{
        struct node{
            int ls, rs;
            ll sum;
            void init() { ls = rs = sum = 0; }
        } t[N * 100];
        int rt[N], tot;
        ll res;
        int newnode(){
            ++tot;
            t[tot].init();
            return tot;
        }
        void init() { memset(rt, 0, sizeof rt);  tot = 0;}
        void update(int &rt, int l,int r,int pos,int v){
            if(!rt)
                rt = newnode();
            t[rt].sum += v;
            if(l == r)
                return;
            int mid = l + r >> 1;
            if(pos <= mid)
                update(t[rt].ls, l, mid, pos, v);
            else
                update(t[rt].rs, mid + 1, r, pos, v);
        }
        void update(int x, int pos, int v) {
            for (; x <= n; x += lowbit(x)) {
                update(rt[x], 1, m, pos, v); 
            }
        }
        void query(int dep, int l,int r,int ql,int qr){
            if(ql > qr)
                return;
            if(l >= ql && r <= qr){
                for (int i = 1; i <= cl;i++)
                    res -= t[L[dep][i]].sum;
                for (int j = 1; j <= cr;j++)
                    res += t[R[dep][j]].sum;
                return;
            }
            int mid = l + r >> 1;
            if(ql <= mid){
                for (int i = 1; i <= cl;i++)
                    L[dep + 1][i] = t[L[dep][i]].ls;
                for (int i = 1; i <= cr;i++)
                    R[dep + 1][i] = t[R[dep][i]].ls;
                query(dep + 1, l, mid, ql, qr);
            }
            if(qr > mid){
                for (int i = 1; i <= cl;i++)
                    L[dep + 1][i] = t[L[dep][i]].rs;
                for (int i = 1; i <= cr;i++)
                    R[dep + 1][i] = t[R[dep][i]].rs;
                query(dep + 1, mid + 1, r, ql, qr);
            }
        }
    } seg;
    int main() {
        m = 2e5;
        while(~scanf("%d%d",&n,&q)){
            for (int i = 1; i <= n;i++)
                scanf("%d", &a[i]);
            seg.init();
            for (int i = 1; i <= n;i++){
                seg.update(i, a[i], a[i]);
            }
            int op, x, y;
            while(q--){
                scanf("%d%d%d", &op, &x, &y);
                if(op == 1){
                    seg.update(x, a[x], -a[x]);
                    a[x] = y;
                    seg.update(x, a[x], a[x]);
                } else {
                    --x;
                    cl = cr = 0;
                    for (int i = x; i; i -= lowbit(i)){
                        L[0][++cl] = seg.rt[i];
                    }
                    for (int i = y; i; i-= lowbit(i)){
                        R[0][++cr] = seg.rt[i];
                    }
                    ll l = 0, r = 0;
                    do{
                        r = l + 1;
                        seg.res = 0;
                        seg.query(0, 1, m, 1, min(1ll * m, r));
                        l = seg.res;
                    } while (l >= r);
                    printf("%lld
    ", l + 1);
                }
            }
        }
        return 0;
    }
    

    L - Loli, Yen-Jen, and a cool problem

    计蒜客 - 42551

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int N = 300000 + 5;
    const int P = 26;
    int n, q;
    char s[N];
    int root, tr[N][P], cnt[N], tot, trie_id[N], sam_pos[N];
    int add(int u, char ch){
        int c = ch - 'A';
        if(!tr[u][c]) tr[u][c] = ++tot;
        u = tr[u][c];
        cnt[u] ++;
        return u;
    }
    struct node{
        int link, len, trans[P], endpos;
    };
    struct SAM{
        node S[2*N];
        int head[2*N], ver[2*N], nxt[2*N];
        int size,tot, fa[2*N][20];
        void add(int x, int y){ver[++tot] = y; nxt[tot] = head[x],head[x] = tot;}
    	SAM():size(1){}
    	int insert(int p, char ch, int cnt){
    		int x = ch - 'A';
    		int np = ++size;
    		S[np].len = S[p].len + 1;
            S[np].endpos = cnt;
    		while(p != 0 && !S[p].trans[x]) S[p].trans[x] = np, p = S[p].link;
    		if(p == 0)S[np].link = 1;
    		else{
    			int q, nq;
    			q = S[p].trans[x];
    			if(S[q].len == S[p].len + 1) S[np].link = q;
    			else{
                    nq = ++size;
    				S[nq] = S[q]; 
                    S[nq].len = S[p].len + 1;
                    S[nq].endpos = 0;
    				S[np].link = S[q].link = nq;
    				while(p != 0 && S[p].trans[x] == q) S[p].trans[x] = nq, p = S[p].link;
    			}
    		}
    		return np;
    	}
        void dfs(int x, int f){
            fa[x][0] = f;
            for(int i=head[x];i;i=nxt[i]){
                int y = ver[i];
                dfs(y, x);
                S[x].endpos += S[y].endpos;
            }
        }
        void build(){
            for(int i=2;i<=size;i++){
                if(S[i].link) add(S[i].link, i);
            }
            dfs(1,0);
            for(int j=1;j<20;j++){
                for(int i=1;i<=size;i++)
                fa[i][j] = fa[fa[i][j-1]][j-1];
            }
        }
        int query(int u, int len){
            for(int i=19;i>=0;i--)if(S[fa[u][i]].len >= len) u = fa[u][i];
            return S[u].endpos;
        }
    }sam;
    void bfs(int u){
        queue<int> q;
        q.push(u);
        sam_pos[u] = 1;
        while(q.size()){
            int x = q.front();q.pop();
            for(int i=0;i<P;i++){
                int y = tr[x][i];
                if(!y)continue;
                q.push(y);
                sam_pos[y] = sam.insert(sam_pos[x], 'A'+i, cnt[y]);
            }
        }
    }
    int main() {
        scanf("%d%d",&n,&q);
        scanf("%s",s+1);
        root = tot = 1;
        trie_id[1] = add(root, s[1]);
        for(int i=2;i<=n;i++){
            int fa;scanf("%d",&fa);
            trie_id[i] = add(trie_id[fa], s[i]);
        }
        bfs(root);
        sam.build();
        while(q--){
            int x, len;scanf("%d%d",&x, &len);
            printf("%d
    ", sam.query(sam_pos[trie_id[x]], len));
        }
        return 0;
    }
    /*
    6 3
    ABABBA
    1 1 3 3 4
    2 2
    2 1
    6 4
    */
    

    M - Kill the tree

    计蒜客 - 42552

    对于以 x 为根的某棵子树,其重心只可能是 x,或者在 x 的重儿子上,所以只需要将 以x 的重儿子 y 为根的子树的重心向上提就好。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const int N = 200000 + 5;
    
    int head[N], ver[N << 1], nxt[N << 1], tot;
    int n, f[N], son[N];
    ll d[N],sz[N];
    vector<int> res[N];
    void add(int x,int y){
        ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
    }
    void dfs(int x,int fa){
        sz[x] = 1;
        for (int i = head[x]; i;i=nxt[i]){
            int y = ver[i];
            if(y == fa)
                continue;
            f[y] = x;
            dfs(y, x);
            sz[x] += sz[y];
            d[x] += d[y] + sz[y];
            if(sz[y] >= sz[son[x]])
                son[x] = y;
        }
        if(sz[x] == 1 || sz[son[x]] * 2 < sz[x]){//sz[son[x]]*2<sz[x]表示重心是x,因为重心如果从x向下移只会使得更加不平衡
            res[x].push_back(x);
            return;
        }
        for (int j = 0; j < res[son[x]].size();j++){
            int v = res[son[x]][j];
            while (v != x && sz[v] < sz[x] - sz[v])//不断向上提
                v = f[v];
            res[x].push_back(v);
            if (v != x && sz[v] == sz[x] - sz[v])//此时发现有存在两个重心的情况
                res[x].push_back(f[v]);
        }
        sort(res[x].begin(), res[x].end());
        res[x].erase(unique(res[x].begin(), res[x].end()), res[x].end());
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i < n;i++){
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            add(y, x);
        }
        dfs(1, 0);
        for (int i = 1; i <= n;i++){
            if(res[i].size() == 1)
                printf("%d
    ", res[i][0]);
            else
                printf("%d %d
    ", res[i][0], res[i][1]);
        }
        return 0;
    }
    
  • 相关阅读:
    iOS 自动化测试踩坑(二):Appium 架构原理、环境命令、定位方式
    干货 | 掌握 Selenium 元素定位,解决 Web 自动化测试痛点
    代理技术哪家强?接口 Mock 测试首选 Charles
    浅谈MVC缓存
    PetaPoco 快速上手
    解释器模式(26)
    享元模式(25)
    中介者模式(24)
    职责链模式(23)
    命令模式(22)
  • 原文地址:https://www.cnblogs.com/1625--H/p/12470665.html
Copyright © 2011-2022 走看看