Submission #1301936

#TimeUsernameProblemLanguageResultExecution timeMemory
1301936tudor_costinDynamic Diameter (CEOI19_diameter)C++20
100 / 100
3230 ms216404 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int Nmax=1e5+5;
class AINT
{
private:
    vector<int> aint;
    vector<int> lazy;
    int n;
public:
    AINT(int siz):lazy(4*siz+5,0), aint(4*siz+5,0)
    {
        n=siz;
    }
    void propagate(int nod)
    {
        if(lazy[nod]==0) return;
        aint[2*nod]+=lazy[nod];
        aint[2*nod+1]+=lazy[nod];
        lazy[2*nod]+=lazy[nod];
        lazy[2*nod+1]+=lazy[nod];
        lazy[nod]=0;
        return;
    }
    int getmax()
    {
        return aint[1];
    }
    void update(int nod,int l,int r,int st,int dr,int val)
    {
        if(st<=l && r<=dr)
        {
            aint[nod]+=val;
            lazy[nod]+=val;
            return;
        }
        int mid=(l+r)/2;
        propagate(nod);
        if(dr<=mid) update(2*nod,l,mid,st,dr,val);
        else if(mid<st) update(2*nod+1,mid+1,r,st,dr,val);
        else
        {
            update(2*nod,l,mid,st,mid,val);
            update(2*nod+1,mid+1,r,mid+1,dr,val);
        }
        aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }
    void upd(int l,int r,int val)
    {
        update(1,0,n-1,l,r,val);
    }
};
vector<AINT> aints[Nmax];
multiset<int> bigC[Nmax];
struct edge
{
    int u;
    int v;
    int cost;
};
struct information
{
    int tata;
    int l;
    int r;
};
edge edges[Nmax];
vector<pair<int,int>> g[Nmax];
bool taken[Nmax];
int siz[Nmax],fc[Nmax],frunze[Nmax];
unordered_map<int,information> interv[Nmax];
unordered_map<int,int> nextCentroid[Nmax];
unordered_map<int,int> pozinG[Nmax];
multiset<int> allvals;
void getsizes(int nod,int pr)
{
    siz[nod]=1;
    for(auto [u,id]:g[nod])
    {
        if(!taken[u] && u!=pr)
        {
            getsizes(u,nod);
            siz[nod]+=siz[u];
        }
    }
    ///cout<<nod<<' '<<pr<<' '<<siz[nod]<<'\n';
}
void getfrunze(int nod,int pr)
{
    frunze[nod]=0;
    bool ok=0;
    for(auto [u,id]:g[nod])
    {
        if(!taken[u] && u!=pr)
        {
            getfrunze(u,nod);
            frunze[nod]+=frunze[u];
            ok=1;
        }
    }
    if(!ok) frunze[nod]++;
}
int getcentroid(int nod,int pr,int tot)
{
    for(auto [u,id]:g[nod])
    {
        if(taken[u] || u==pr) continue;
        if(2*siz[u]>tot)
        {
            return getcentroid(u,nod,tot);
        }
    }
    return nod;
}
void buildaint(int nod,int pr,AINT &cur,int cntfr,int cost,int tata,int centroid)
{
    int l=cntfr,r=cntfr+frunze[nod]-1;
    cur.upd(l,r,cost);
    for(auto [u,id]:g[nod])
    {
        if(taken[u] || u==pr) continue;
        buildaint(u,nod,cur,cntfr,edges[id].cost,tata,centroid);
        interv[id][centroid]= {tata,cntfr,cntfr+frunze[u]-1};
        cntfr+=frunze[u];
    }
    return;
}
int getsum(multiset<int>& s)
{
    if(s.size()>=2)
    {
        auto it=s.rbegin();
        int sum=(*it);
        it++;
        sum+=(*it);
        return sum;
    }
    else return (*s.rbegin());
}
int decompBuild(int nod)
{
    getsizes(nod,0);
    int centroid=getcentroid(nod,0,siz[nod]);
    getfrunze(centroid,0);
    int cnt=0;
    for(auto [u,id]:g[centroid])
    {
        ///cout<<centroid<<' '<<u<<' '<<id<<'\n';
        if(taken[u]) continue;
        pozinG[u][centroid]=cnt;
        cnt++;
        AINT cur(frunze[u]);
        ///cout<<centroid<<' '<<u<<' '<<id<<'\n';
        interv[id][centroid]= {u,0,frunze[u]-1};
        ///cout<<centroid<<' '<<u<<' '<<id<<'\n';
        buildaint(u,centroid,cur,0,edges[id].cost,u,centroid);
        ///cout<<centroid<<' '<<u<<' '<<id<<' '<<cur.getmax()<<'\n';
        bigC[centroid].insert(cur.getmax());
        aints[centroid].push_back(cur);
        ///cout<<centroid<<' '<<u<<' '<<id<<'\n';
    }
    if(!bigC[centroid].empty()) allvals.insert(getsum(bigC[centroid]));
    taken[centroid]=1;
    for(auto [u,id]:g[centroid])
    {
        if(taken[u]) continue;
        nextCentroid[u][centroid]=decompBuild(u);
    }
    return centroid;
}
void update(int centroid,int id,int prv,int val)
{
    ///cout<<centroid<<' '<<id<<' '<<prv<<' '<<val<<'\n';
    auto [tata,l,r]=interv[id][centroid];
    if(!bigC[centroid].empty())
    {
        int poz=pozinG[tata][centroid];
        int cur=aints[centroid][poz].getmax();
        int curval=getsum(bigC[centroid]);
        ///cout<<curval<<'\n';
        allvals.erase(allvals.find(curval));
        bigC[centroid].erase(bigC[centroid].find(cur));
        ///cout<<l<<' '<<r<<'\n';
        aints[centroid][poz].upd(l,r,-prv);
        aints[centroid][poz].upd(l,r,val);
        int nw=aints[centroid][poz].getmax();
        bigC[centroid].insert(nw);
        ///cout<<centroid<<' '<<getsum(bigC[centroid])<<' '<<"UPDATE CENTROID"<<'\n';
        allvals.insert(getsum(bigC[centroid]));
    }
    if(edges[id].u==centroid && edges[id].v==tata) return;
    if(edges[id].u==tata && edges[id].v==centroid) return;
    int nxt=nextCentroid[tata][centroid];
    if(nxt!=0) update(nxt,id,prv,val);
    return;
}
signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int n,q,w;
    cin>>n>>q>>w;
    for(int i=1; i<n; i++)
    {
        cin>>edges[i].u>>edges[i].v>>edges[i].cost;
        g[edges[i].u].push_back({edges[i].v,i});
        g[edges[i].v].push_back({edges[i].u,i});
    }
    int firstCentroid=decompBuild(1);
    int last=0;
    ///cout<<111<<'\n';
    while(q--)
    {
        int d,e;
        cin>>d>>e;
        d=(d+last)%(n-1);
        e=(e+last)%w;
        d++;
        ///cout<<d<<' '<<e<<'\n';
        update(firstCentroid,d,edges[d].cost,e);
        edges[d].cost=e;
        last=(*allvals.rbegin());
        cout<<last<<'\n';
    }
    return 0;
}
#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...