Submission #1098790

#TimeUsernameProblemLanguageResultExecution timeMemory
1098790damwuanDynamic Diameter (CEOI19_diameter)C++17
100 / 100
2865 ms351420 KiB
#include<bits/stdc++.h>
using namespace std;
#define int ll
#define fi first
#define se second
#define pb push_back
#define all(x) x.begin(),x.end()
#define for1(i,x,n) for(int i=x;i<=n;i++)
#define for2(i,x,n) for(int i=x;i>=n;i--)

typedef long long ll;
typedef pair<int,int> pii;

const ll maxn = 1e5 + 3;
const ll mod  = 1e9 + 7;
const ll inf  = 1e18;

int n,q;
int mx[maxn*4];
int sz[maxn],dep[maxn],in[maxn],out[maxn],Time,uu[maxn],vv[maxn],w[maxn],a[maxn],b[maxn],k[maxn],ans[maxn];
bool used[maxn],dd[maxn];
vector<int> adj[maxn],qr[maxn],go[maxn];
void Udp(int u,int v,int id=1,int l=1,int r=n)
{
    if (l==r)
    {
        mx[id]=v;
        return;
    }
    int mid=l+r>>1;
    if (u<=mid) Udp(u,v,id*2,l,mid);
    else Udp(u,v,id*2+1,mid+1,r);
    mx[id]=max(mx[id*2],mx[id*2+1]);
}


struct T
{
    int cen,up,dep,in,out;
};
vector<T> L[maxn];

struct Node
{
    pii x, y;
};
Node Merge(Node a,Node b)
{
    if (a.x<b.x) swap(a,b);
    if (a.x.se!=b.x.se) a.y=max(a.y,b.x);
    if (a.x.se!=b.y.se) a.y=max(a.y,b.y);
    return a;
}
struct segtree
{
    int nn;
    vector<Node> st;
    vector<int> lazy;
    void init(int x)
    {
        nn=x;
        st.resize(nn*4+2,(Node){{-1,-1},{-1,-1}});
        lazy.resize(nn*4+2,0);
    }
    void push(int id)
    {
        int& val=lazy[id];
        if (st[id*2].x.fi!=-1) st[id*2].x.fi+=val;
        if (st[id*2].y.fi!=-1) st[id*2].y.fi+=val;
        lazy[id*2]+=val;
        if (st[id*2+1].x.fi!=-1) st[id*2+1].x.fi+=val;
        if (st[id*2+1].y.fi!=-1) st[id*2+1].y.fi+=val;
        lazy[id*2+1]+=val;
        val=0;
    }

    void Update(int u,pii v,int id,int l,int r)
    {
        if (l==r)
        {
            st[id]={v,{-1,-1}};
            return;
        }
        if (lazy[id]) push(id);
        int mid=l+r>>1;
        if (u<=mid) Update(u,v,id*2,l,mid);
        else Update(u,v,id*2+1,mid+1,r);
        st[id]=Merge(st[id*2],st[id*2+1]);
    }
    void Update2(int u,int v,int val,int id,int l,int r)
    {
        if (u>r || v<l) return;
        if (u<=l && r<=v)
        {
            if (st[id].x.fi!=-1) st[id].x.fi+=val;
            if (st[id].y.fi!=-1) st[id].y.fi+=val;
            lazy[id]+=val;
            return;
        }
        if (lazy[id]) push(id);
        int mid=l+r>>1;
        Update2(u,v,val,id*2,l,mid);
        Update2(u,v,val,id*2+1,mid+1,r);
        st[id]=Merge(st[id*2],st[id*2+1]);
    }
}tree[maxn];

void dfs_sz(int u,int pre)
{
    sz[u]=1;
    for(int i: adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (v==pre || used[v]) continue;
        dfs_sz(v,u);
        sz[u]+=sz[v];
    }
}

int Find_cen(int u,int pre,int treesz)
{
    for(int i:adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (v==pre || used[v]) continue;
        if (sz[v]*2>treesz) return Find_cen(v,u,treesz);
    }
    return u;
}

void dfs_dep(int u,int pre)
{
    for(int i: adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (v==pre || used[v]) continue;
        dep[v]=dep[u]+w[i];
//        cerr<<" d "<<v<<' '<< dep[v]<<'\n';
        dfs_dep(v,u);
    }
}

void initial(int u,int pre,int cen,int rt)
{
    in[u]=++Time;
    for(int i: adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (v==pre || used[v]) continue;
        initial(v,u,cen,rt);
    }
    out[u]=Time;
    L[u].pb({cen,rt,dep[u],in[u],out[u]});
}


void centroid(int u)
{
    dfs_sz(u,-1);
    if (sz[u]==1) return;
//    cerr<< sz[u]<<'\n';
    
    u=Find_cen(u,-1,sz[u]);
//    cerr<<"cen "<< u<<"\n";
    used[u]=1;
    dep[u]=0;
    dfs_dep(u,-1);
    Time=1;
    for(int i:adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (used[v]) continue;
        initial(v,u,u,v);
    }
    L[u].pb({u,u,0,1,Time});
    tree[u].init(Time);
    for(int i: adj[u])
    {
        int v=u^uu[i]^vv[i];
        if (used[v]) continue;
        centroid(v);
    }
}

void Add(int u)
{
//    cerr<< "add dinh "<<u<<' '<<L[u].size()<<'\n';
    for(auto x:L[u])
    {
//        cerr<< x.cen<<' '<<x.up<<' '<< x.dep<<'\n';
        tree[x.cen].Update(x.in,{x.dep,x.up},1,1,tree[x.cen].nn);
        if (tree[x.cen].st[1].y.fi!=-1) Udp(x.cen,tree[x.cen].st[1].x.fi+tree[x.cen].st[1].y.fi);
    }
//    cerr<<tree[2].st[1].x.fi<<' '<<tree[2].st[1].y.fi<<'\n';
}

void sol()
{
    int WW;
    cin >> n>> q>>WW;
    for1(i,1,n-1)
    {
        cin >> uu[i]>>vv[i]>>w[i];
        adj[uu[i]].pb(i);
        adj[vv[i]].pb(i);
    }
    centroid(1);
    for1(i,1,n) Add(i);
    int last=0,d=0,e=0;
    for1(i,1,q)
    {
        cin >> d>>e;
        d=(d+last)%(n-1);
        e=(e+last)%WW;
        int j=d+1;
        for(auto x: L[uu[j]])
        {
            for(auto y:L[vv[j]])
            {
                if (x.cen==y.cen)
                {
                    T g;
                    if (x.in<y.in) g=y;
                    else g=x;
                    tree[g.cen].Update2(g.in,g.out,e-w[j],1,1,tree[x.cen].nn);
                    if (tree[x.cen].st[1].y.fi!=-1) Udp(x.cen,tree[x.cen].st[1].x.fi+tree[x.cen].st[1].y.fi);
                }
            }
        }
        w[j]=e;
        last=mx[1];
        cout << last<<'\n';
    }

}


int32_t main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int t=1;//cin >> t;
    while (t--) sol();
}
/*
5
5 3 5 3 5
10 1 20 1 20
*/

Compilation message (stderr)

diameter.cpp: In function 'void Udp(ll, ll, ll, ll, ll)':
diameter.cpp:30:14: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   30 |     int mid=l+r>>1;
      |             ~^~
diameter.cpp: In member function 'void segtree::Update(ll, pii, ll, ll, ll)':
diameter.cpp:85:18: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   85 |         int mid=l+r>>1;
      |                 ~^~
diameter.cpp: In member function 'void segtree::Update2(ll, ll, ll, ll, ll, ll)':
diameter.cpp:101:18: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  101 |         int mid=l+r>>1;
      |                 ~^~
#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...