Submission #859615

# Submission time Handle Problem Language Result Execution time Memory
859615 2023-10-10T11:26:04 Z heeheeheehaaw Traffickers (RMI18_traffickers) C++17
100 / 100
3165 ms 149328 KB
#include <bits/stdc++.h>
#define int long long

using namespace std;

int n, k;
int tin[30005], tout[30005], anc[30005][23], mat[23][23], timer, cnt;
int heavy[30005], head[30005], pos[30005], hei[30005], siz[30005];
int32_t aint[30000 * 4 + 5][23][23];
vector<int> adj[30005];

bool isanc(int u, int v)
{
    return ((tin[u] <= tin[v]) && (tout[u] >= tout[v]));
}

int lca(int u, int v)
{
    if(isanc(u, v)) return u;
    if(isanc(v, u)) return v;
    for(int i = 19; i >= 0; i--)
        if(!isanc(anc[u][i], v))
            u = anc[u][i];
    return anc[u][0];
}

void update(int nod, int st, int dr, int poz, int val, int d1, int d2)
{
    if(st == dr)
    {
        aint[nod][d1][d2] += val;
        return;
    }

    int mij = (st + dr) / 2;
    if(poz <= mij)
        update(nod * 2, st, mij, poz, val, d1, d2);
    else
        update(nod * 2 + 1, mij + 1, dr, poz, val, d1, d2);
    aint[nod][d1][d2] = aint[nod * 2][d1][d2] + aint[nod * 2 + 1][d1][d2];
}

int query(int nod, int st, int dr, int le, int ri, int d1, int d2)
{
    if(le > ri)
        return 0;
    if(le == st && ri == dr)
        return aint[nod][d1][d2];
    int mij = (st + dr) / 2;
    return query(nod * 2, st, mij, le, min(mij, ri), d1, d2) +
           query(nod * 2 + 1, mij + 1, dr, max(le, mij + 1), ri, d1, d2);
}

void dfs(int nod, int p)
{
    siz[nod] = 1;
    anc[nod][0] = p;
    for(int i = 1; i <= 19; i++)
        anc[nod][i] = anc[anc[nod][i - 1]][i - 1];
    timer++, tin[nod] = timer;

    int maxx = -1;
    for(auto it : adj[nod])
        if(it != p)
        {
            hei[it] = hei[nod] + 1;
            dfs(it, nod);
            siz[nod] += siz[it];
            if(siz[it] > maxx)
                maxx = siz[it], heavy[nod] = it;
        }

    timer++, tout[nod] = timer;
}

void decompose(int nod, int h)
{
    head[nod] = h, pos[nod] = ++cnt;
    if(heavy[nod] != -1)
        decompose(heavy[nod], h);
    for(auto it : adj[nod])
        if(anc[nod][0] != it && it != heavy[nod])
            decompose(it, it);
}

vector<int> getpath(int a, int b, int l)
{
    vector<int> ans, v2;
    while(a != l)
        ans.push_back(a), a = anc[a][0];
    ans.push_back(l);
    while(b != l)
        v2.push_back(b), b = anc[b][0];
    for(int i = (int)v2.size() - 1; i >= 0; i--)
        ans.push_back(v2[i]);
    return ans;
}

void updatepath(int a, int b, int val)
{
    int l = lca(a, b);
    vector<int> path = getpath(a, b, l);
    int d = (int)path.size();
    cnt = 0;
    for(auto it : path)
    {
        update(1, 1, n, pos[it], val, d, cnt);
        cnt++;
    }

}

int calc(int a, int b, int t1, int t2)
{
    for(int d = 1; d <= 20; d++)
        for(int x = 0; x < d; x++)
            mat[d][x] = 0;
    for(; head[a] != head[b]; b = anc[head[b]][0])
    {
        if(hei[head[a]] > hei[head[b]])
            swap(a, b);
        for(int d = 1; d <= 20; d++)
            for(int x = 0; x < d; x++)
                mat[d][x] += query(1, 1, n, pos[head[b]], pos[b], d, x);
    }

    if(hei[a] > hei[b])
        swap(a, b);
    int rez = 0;
    for(int d = 1; d <= 20; d++)
    {
        for(int x = 0; x < d; x++)
        {
            mat[d][x] += query(1, 1, n, pos[a], pos[b], d, x);
            int st = (t1 - (t1 % d) + x);
            if(st >= t1) st -= d;
            int dr = (t2 - (t2 % d)) + x;
            if(dr > t2) dr -= d;
            rez = rez + 1LL * ((dr - st) / d) * mat[d][x];
        }
    }

    return rez;
}

signed main()
{
    cin>>n;
    heavy[n] = -1;
    for(int i = 1; i < n; i++)
    {
        int a, b;
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
        heavy[i] = -1;
    }

    dfs(1, 1);
    decompose(1, 1);

    cin>>k;
    cnt = 0;
    for(int i = 1; i <= k; i++)
    {
        int a, b;
        cin>>a>>b;
        updatepath(a, b, 1);
    }

    int q;
    cin>>q;
    for(int i = 1; i <= q; i++)
    {
        int tip, a, b;
        cin>>tip>>a>>b;
        if(tip == 1)
            updatepath(a, b, 1);
        else if(tip == 2)
            updatepath(a, b, -1);
        else
        {
            int t1, t2;
            cin>>t1>>t2;
            cout<<calc(a, b, t1, t2)<<'\n';
        }
    }

    return 0;
}
# Verdict Execution time Memory Grader output
1 Correct 1 ms 4696 KB Output is correct
2 Correct 13 ms 10844 KB Output is correct
3 Correct 15 ms 10844 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 176 ms 75288 KB Output is correct
2 Correct 208 ms 75100 KB Output is correct
3 Correct 142 ms 75612 KB Output is correct
4 Correct 176 ms 75424 KB Output is correct
5 Correct 201 ms 75260 KB Output is correct
6 Correct 191 ms 75380 KB Output is correct
7 Correct 180 ms 75336 KB Output is correct
8 Correct 149 ms 75408 KB Output is correct
9 Correct 171 ms 75608 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 1955 ms 148532 KB Output is correct
2 Correct 1622 ms 149328 KB Output is correct
3 Correct 1632 ms 148596 KB Output is correct
4 Correct 2579 ms 147780 KB Output is correct
5 Correct 3165 ms 147948 KB Output is correct
6 Correct 1619 ms 149260 KB Output is correct
7 Correct 1844 ms 149204 KB Output is correct
8 Correct 1795 ms 148836 KB Output is correct