MnZn 求助淀粉树
查看原帖
MnZn 求助淀粉树
420129
Nt_Tsumiki楼主2024/2/28 20:46

T 死了,合理怀疑是哪里复杂度写假了

大体思路是树剖求 lca 加 fhq 加淀粉树

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <random>

#define N 150001

using namespace std;
int n,q,A,tn,a[N],b[N];

int cnt,head[N];
struct Node { int to,nxt,dis; }e[N<<8];

void add(int u,int v,int w) { e[++cnt]=Node{v,head[u],w},head[u]=cnt; }

int siz[N],son[N],fa[N],top[N],dep[N];
long long dis[N];

void dfs1(int u,int Fa) {
    siz[u]=1,dep[u]=dep[fa[u]=Fa]+1;
    for (int i=head[u];i;i=e[i].nxt) {
        int v=e[i].to;
        if (v==Fa) continue;
        dis[v]=dis[u]+e[i].dis;
        dfs1(v,u);
        siz[u]+=siz[v];
        if (siz[v]>siz[son[u]]) son[u]=v;
    }
}

void dfs2(int u,int Top) {
    top[u]=Top;
    if (son[u]) dfs2(son[u],Top);
    for (int i=head[u];i;i=e[i].nxt) {
        int v=e[i].to;
        if (v==fa[u] or v==son[u]) continue;
        dfs2(v,v);
    }
}

int LCA(int u,int v) {
    while (top[u]!=top[v]) {
        if (dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]<dep[v]?u:v;
}

int tcnt,Rt[N][2];
struct Tree { long long val,sum; int key,siz,w,ls,rs; }t[N<<5];

void upd(int x) { t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum+t[x].val,t[x].siz=t[t[x].ls].siz+t[t[x].rs].siz+1; }

void merge(int &rt,int x,int y) {
    if (!x or !y) return rt=x+y,void();
    if (t[x].key<=t[y].key) rt=x,merge(t[rt].rs,t[x].rs,y);
    else rt=y,merge(t[rt].ls,x,t[y].ls);
    upd(rt);
}

void split(int rt,int &x,int &y,int k) {
    if (!rt) return x=y=0,void();
    if (t[rt].w<=k) x=rt,split(t[rt].rs,t[x].rs,y,k),upd(x);
    else y=rt,split(t[rt].ls,x,t[y].ls,k),upd(y);
}

void ins(int &rt,int val,int w) {
    int x=0,y=0,z=0;
    split(rt,x,y,w);
    t[z=++tcnt]=Tree{val,val,rand(),1,w,0,0};
    merge(x,x,z); merge(rt,x,y);
}

long long qry(int rt,int l,int r,long long k) {
    if (!rt) return 0;
    int x=0,y=0,z=0;
    split(rt,x,y,l-1); split(y,y,z,r);
    long long res=t[y].sum+k*t[y].siz;
    merge(y,y,z); merge(rt,x,y);
    return res;
}

int rt,S,_siz[N],_fa[N],msz[N],vis[N];

void find_rt(int u,int las) {
    _siz[u]=1,msz[u]=0;
    for (int i=head[u];i;i=e[i].nxt) {
        int v=e[i].to;
        if (vis[v] or v==las) continue;
        find_rt(v,u);
        _siz[u]+=_siz[v],msz[u]=max(msz[u],_siz[v]);
    }
    msz[u]=max(msz[u],S-_siz[u]);
    if (msz[u]<msz[rt]) rt=u;
}

void dfs(int u) {
    for (int i=head[u];i;i=e[i].nxt) {
        int v=e[i].to;
        if (vis[v]) continue;
        int tS=S;
        S=_siz[v]>_siz[u]?S-_siz[u]:_siz[v],rt=0;
        find_rt(v,0); vis[rt]=1,_fa[rt]=u;
        dfs(rt);
        S=tS;
    }
}

void upd(int x,int k) {
    int u=x,v=_fa[x];
    while (u) {
        long long d=dis[x]+dis[u]-2*dis[LCA(x,u)];
        ins(Rt[u][0],d,k);
        if (v) {
            d=dis[x]+dis[v]-2*dis[LCA(x,v)];
            ins(Rt[u][1],d,k);
        }
        u=v,v=_fa[v];
    }
}

long long ask(int x,int l,int r) {
    int u=x,v=0; long long res=0;
    while (u) {
        long long d=dis[x]+dis[u]-2*dis[LCA(x,u)];
        res+=qry(Rt[u][0],l,r,d);
        if (v) res-=qry(Rt[v][1],l,r,d);
        // printf("%d:%lld\n",u,res);
        v=u,u=_fa[u];
    }
    return res;
}

signed main() {
    srand(388651);
    cin>>n>>q>>A;
    for (int i=1;i<=n;i++) {
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b+1,b+n+1); tn=unique(b+1,b+n+1)-b-1;
    for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tn+1,a[i])-b;
    for (int i=1,u,v,w;i<n;i++) {
        cin>>u>>v>>w;
        add(u,v,w),add(v,u,w);
    }
    msz[rt=0]=1e9,S=n;
    find_rt(1,0); vis[rt]=1;
    dfs(rt);
    dfs1(1,0); dfs2(1,1);
    for (int i=1;i<=n;i++) upd(i,a[i]);
    long long las=0;
    for (int i=1,u,a0,b0;i<=q;i++) {
        cin>>u>>a0>>b0;
        int L=min((a0+las)%A,(b0+las)%A),R=max((a0+las)%A,(b0+las)%A);
        L=lower_bound(b+1,b+tn+1,L)-b;
        R=upper_bound(b+1,b+tn+1,R)-b-1;
        cout<<(las=ask(u,L,R))<<'\n';
    }
    return 0;
}
2024/2/28 20:46
加载中...