Submission #1314334

#TimeUsernameProblemLanguageResultExecution timeMemory
1314334Zbyszek99Dynamic Diameter (CEOI19_diameter)C++20
100 / 100
3213 ms206112 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

struct segtree
{
    pll* max_;
    ll* oper;
    int tree_siz;
    void setup(int n, vi& x)
    {
        tree_siz = (1<<(__lg(n)+2))-1;
        max_ = new pll[tree_siz+1];
        oper = new ll[tree_siz+1];
        rep2(i,tree_siz/2+1,tree_siz) 
        {
            if(i-(tree_siz/2+1) < siz(x)) max_[i] = {0,x[i-(tree_siz/2+1)]};
            else max_[i] = {-1e9,-1};
            oper[i] = 0;
        }
        for(int i = tree_siz/2; i >= 1; i--)
        {
            max_[i] = max(max_[i*2],max_[i*2+1]);
            oper[i] = 0;
        }
    }
    void push(int v)
    {
        max_[v*2].ff += oper[v];
        max_[v*2+1].ff += oper[v];
        oper[v*2] += oper[v];
        oper[v*2+1] += oper[v];
        oper[v] = 0;
    }
    void add(int akt, int p1, int p2, int s1, int s2, ll x)
    {
        if(p2 < s1 || p1 > s2) return;
        if(p1 >= s1 && p2 <= s2)
        {
            max_[akt].ff += x;
            oper[akt] += x;
            return;
        }
        push(akt);
        add(akt*2,p1,(p1+p2)/2,s1,s2,x);
        add(akt*2+1,(p1+p2)/2+1,p2,s1,s2,x);
        max_[akt] = max(max_[akt*2],max_[akt*2+1]);
    }
    pll get(int akt, int p1, int p2, int s1, int s2)
    {
        if(p2 < s1 || p1 > s2) return {-1e9,1};
        if(p1 >= s1 && p2 <= s2) return max_[akt];
        push(akt);
        return max(get(akt*2,p1,(p1+p2)/2,s1,s2),get(akt*2+1,(p1+p2)/2+1,p2,s1,s2));
    }
    void add_seg(int l, int r, ll x)
    {
        add(1,0,tree_siz/2,l,r,x);
    }
    pll get_max(int l, int r)
    {
        if(l > r) return {-1e9,0};
        return get(1,0,tree_siz/2,l,r);
    }
};

struct centr_info
{
    int v,s_l,s_r,l,r;
};

segtree trees[100001];
vector<pii> graph[100001];
bool odw[100001];
ll cost[100001];
int sub[100001];
vector<centr_info> vert_info[100001];
vector<centr_info> edge_info[100001];
int v1=1,v2=1;
int pre[100001];
int maxpre[100001];
int cur_pre = 0;
vi pre_ls;

void dfs_sub(int v, int pop)
{
    sub[v] = 1;
    forall(it,graph[v])
    {
        if(it.ff != pop && !odw[it.ff])
        {
            dfs_sub(it.ff,v);
            sub[v] += sub[it.ff];
        }
    }
}

void dfs_pre(int v, int pop)
{
    pre_ls.pb(v);
    pre[v] = cur_pre++;
    maxpre[v] = pre[v];
    forall(it,graph[v])
    {
        if(it.ff != pop && !odw[it.ff])
        {
            dfs_pre(it.ff,v);
            maxpre[v] = maxpre[it.ff];
        }
    }
}

void dfs_add(int v, int pop, int centr, int s_l, int s_r)
{
    vert_info[v].pb({centr,s_l,s_r,pre[v],maxpre[v]});
    forall(it,graph[v])
    {
        if(it.ff != pop && !odw[it.ff])
        {
            edge_info[it.ss].pb({centr,s_l,s_r,pre[it.ff],maxpre[it.ff]});
            dfs_add(it.ff,v,centr,s_l,s_r);
        }
    }
}

void centroid(int v, int n)
{
    dfs_sub(v,v);
    int pop = v;
    while(true)
    {
        pii best = {0,0};
        forall(it,graph[v])
        {
            if(it.ff != pop && !odw[it.ff])
            {
                best = max(best,{sub[it.ff],it.ff});
            }
        }
        if(best.ff > n/2)
        {
            pop = v;
            v = best.ss;
        }
        else break;
    }
    odw[v] = 1;
    dfs_sub(v,v);
    cur_pre = 0;
    pre_ls = {};
    dfs_pre(v,v);
    trees[v].setup(n,pre_ls);
    vert_info[v].pb({v,-1,-1,0,cur_pre-1});
    forall(it,graph[v])
    {
        if(odw[it.ff]) continue;
        dfs_add(it.ff,v,v,pre[it.ff],maxpre[it.ff]);
        edge_info[it.ss].pb({v,pre[it.ff],maxpre[it.ff],pre[it.ff],maxpre[it.ff]});
    }
    forall(it,graph[v])
    {
        if(!odw[it.ff]) centroid(it.ff,sub[it.ff]);
    }
}   

ll query(int e, ll c, bool is = 0)
{
    forall(it,edge_info[e]) 
    {
        trees[it.v].add_seg(it.l,it.r,(!is ? -cost[e] : 0)+c);
    }
    cost[e] = c;
    pll ans1 = {-1,-1};
    pll ans2 = {-1,-1};
    forall(it,vert_info[v1]) 
    {
        pll a1 = trees[it.v].get_max(0,it.s_l-1);
        a1.ff += trees[it.v].get_max(it.l,it.l).ff;
        pll a2 = trees[it.v].get_max(it.s_r+1,trees[it.v].tree_siz/2);
        a2.ff += trees[it.v].get_max(it.l,it.l).ff;
        ans1 = max({ans1,a1,a2});
    }
    forall(it,vert_info[v2]) 
    {
        pll a1 = trees[it.v].get_max(0,it.s_l-1);
        a1.ff += trees[it.v].get_max(it.l,it.l).ff;
        pll a2 = trees[it.v].get_max(it.s_r+1,trees[it.v].tree_siz/2);
        a2.ff += trees[it.v].get_max(it.l,it.l).ff;
        ans2 = max({ans2,a1,a2});
    }
    if(ans2.ff > ans1.ff) 
    {
        swap(ans1,ans2);
        swap(v1,v2);
    }
    v2 = ans1.ss;
    return ans1.ff;
}   

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    int n,q;
    ll xd;
    cin >> n >> q >> xd;
    rep(i,n-1)
    {
        int a,b;
        cin >> a >> b >> cost[i+1];
        graph[a].pb({b,i+1});
        graph[b].pb({a,i+1});
    }
    centroid(1,n);
    rep2(i,1,n-1) query(i,cost[i],1);
    ll last = 0;
    rep(qq,q)
    {
        int e;
        ll c;
        cin >> e >> c;
        e = (e+last)%(n-1);
        c = (c+last)%xd;
        last = query(e+1,c);
        cout << last << "\n";
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...