Submission #1248253

#TimeUsernameProblemLanguageResultExecution timeMemory
1248253cpdreamerDynamic Diameter (CEOI19_diameter)C++20
100 / 100
2548 ms34856 KiB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define V vector
#define pb push_back
#define all(v) v.begin(),v.end()
const long long MOD=1e9+7;
#define P pair
void file() {
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
}
int up[(int)1e5+1][20];
V<P<int,ll>>adj[(int)1e5+1];
int l[(int)1e5+1];
int r[(int)1e5+1];
int l1[(int)1e5+1];
int r1[(int)1e5+1];
int f[(int)1e5+1];
ll dep[(int)1e5+1];
int d[(int)1e5+1];
int e1[(int)1e5+1];
int e2[(int)1e5+1];
ll ew[(int)1e5+1];
V<int>leaf;
int cnt=0;
int c=0;
void dfs(int n,int p) {
    int lb=INT_MAX,rb=INT_MIN;
    f[n]=c;
    l1[n]=c;
    for (int k=0;k<20;k++) {
        if (k==0) {
            up[n][0]=p;
        }
        else {
            up[n][k]=up[up[n][k-1]][k-1];
        }
        if (up[n][k]==-1) {
            break;
        }
    }
    for (auto [u,w]:adj[n]) {
        if (u==p)continue;
        dep[u]=dep[n]+w;
        d[u]=d[n]+1;
        c++;
        dfs(u,n);
        lb=min(lb,l[u]);
        rb=max(rb,r[u]);
    }
    if (lb==INT_MAX) {
        l[n]=cnt;
        r[n]=cnt;
        cnt++;
        leaf.pb(n);
    }
    else {
        l[n]=lb;
        r[n]=rb;
    }
    r1[n]=c;
}
int kth(int n,int k) {
    int cur=n;
    for (int i=0;i<20;i++) {
        if (((1<<i)&k)!=0) {
            cur=up[cur][i];
        }
    }
    return cur;
}
int lca(int a,int b) {
    if (d[a]<d[b]) {
        swap(a,b);
    }
    a=kth(a,d[a]-d[b]);
    if (a==b) {
        return a;
    }
    for (int j=19;j>=0;j--) {
        if (up[a][j]!=up[b][j]) {
            a=up[a][j];
            b=up[b][j];
        }
    }
    return up[a][0];
}
struct path {
    ll ans;
    int x;
    int y;
    int l;
};
bool cus(path a,path b) {
    return a.ans>b.ans;
}
struct seggy {
private:
    struct node {
        ll d;
    };
    node merge(node a,node b) {
        return {a.d+b.d};
    }
    node single(int v) {
        return {dep[v]};
    }
    node neutral={0LL};
public:
    int size;
    V<node>query;
    void init(int n) {
        size=1;
        while (size<n)size*=2;
        query.assign(2*size,neutral);
    }
    void set(int l,int r,ll v,int x,int lx,int rx) {
        if (lx>=r || rx<=l) {
            return;
        }
        if (l<=lx && rx<=r) {
            query[x]=merge(query[x],{v});
            return;
        }
        int m=(lx+rx)/2;
        set(l,r,v,2*x+1,lx,m);
        set(l,r,v,2*x+2,m,rx);
    }
    void set(int l,int r,ll v) {
        set(l,r,v,0,0,size);
    }
    node calc(int i,int x,int lx,int rx) {
        if (rx-lx==1) {
            return query[x];
        }
        int m=(lx+rx)/2;
        if (i<m) {
            return merge(query[x],calc(i,2*x+1,lx,m));
        }
        return merge(query[x],calc(i,2*x+2,m,rx));
    }
    ll calc(int i) {
        return calc(i,0,0,size).d;
    }
};
seggy euler;
struct segtree {
private:
    struct node {
        ll ans;
        int nd[3];
        ll mx;
    };
    node neutral={-1};
    node single(int v) {
        return {0LL,{v,v,v},dep[v]};
    }
    node merge(node a,node b) {
        if (a.ans==-1)return b;
        if (b.ans==-1)return a;
        V<path>vp;
        for (int i=0;i<2;i++) {
            for (int j=0;j<2;j++) {
                int x=a.nd[i];
                int y=b.nd[j];
                int l=lca(x,y);
                ll ans=euler.calc(f[x])+euler.calc(f[y])-2*euler.calc(f[l]);
                vp.pb({ans,x,y,l});
            }
        }
        vp.pb({a.ans,a.nd[0],a.nd[1],a.nd[2]});
        vp.pb({b.ans,b.nd[0],b.nd[1],b.nd[2]});
        sort(all(vp),cus);
        return {vp[0].ans,{vp[0].x,vp[0].y,vp[0].l},max(a.mx,b.mx)};
    }
    node modification(node a,ll v) {
        node b=a;
        b.mx+=v;
        return b;
    }

public:
    int size;
    V<node>query;
    V<ll>op;
    void init(int n) {
        size=1;
        while (size<n)size*=2;
        query.assign(2*size,neutral);
        op.assign(2*size,0LL);
    }
    void build(V<int>&a,int x,int lx,int rx) {
        if (rx-lx==1) {
            if (lx<a.size()) {
                query[x]=single(a[lx]);
            }
            return;
        }
        int m=(lx+rx)/2;
        build(a,2*x+1,lx,m);
        build(a,2*x+2,m,rx);
        query[x]=merge(query[2*x+1],query[2*x+2]);
    }
    void build(V<int>&a) {
        build(a,0,0,size);
    }
    void set(int l,int r,ll v,int x,int lx,int rx) {
        if (lx>=r || rx<=l) {
            return;
        }
        if (l<=lx && rx<=r) {
            op[x]+=v;
            query[x]=modification(query[x],v);
            return;
        }
        int m=(lx+rx)/2;
        set(l,r,v,2*x+1,lx,m);
        set(l,r,v,2*x+2,m,rx);
        query[x]=modification(merge(query[2*x+1],query[2*x+2]),op[x]);
    }
    void set(int l,int r,ll v) {
        set(l,r,v,0,0,size);
    }
    ll calc() {
        return max(query[0].ans,query[0].mx);
    }
};
void solve() {
    int n,q;
    ll x;
    cin>>n>>q>>x;
    for (int i=0;i<n-1;i++) {
        int a,b;
        ll w;
        cin>>a>>b>>w;
        adj[a].pb({b,w});
        adj[b].pb({a,w});
        e1[i]=a,e2[i]=b,ew[i]=w;
    }
    dep[1]=0LL;
    dfs(1,-1);
    euler.init(n);
    for (int i=1;i<=n;i++) {
        euler.set(f[i],f[i]+1,dep[i]);
    }
    segtree tree;
    tree.init((int)leaf.size());
    tree.build(leaf);
    ll last=0;
    while (q--) {
        ll de;
        ll dw;
        cin>>de>>dw;
        de=(de+last)%(n-1);
        dw=(dw+last)%x;
        int nd;
        if (d[e1[de]]<d[e2[de]]) {
            nd=e2[de];
        }
        else
            nd=e1[de];
        euler.set(l1[nd],r1[nd]+1,dw-ew[de]);
        tree.set(l[nd],r[nd]+1,dw-ew[de]);
        ew[de]=dw;
        last=tree.calc();
        cout<<last<<endl;
    }
}
int main(){
    //file();
    solve();

}

Compilation message (stderr)

diameter.cpp: In function 'void file()':
diameter.cpp:10:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   10 |     freopen("input.txt","r",stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:11:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   11 |     freopen("output.txt","w",stdout);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...