[HNOI 2015]开店

题意:求“方便值”

思路:树链剖分维护修改即可,似乎还有点分树的做法~

#include<bits/stdc++.h>
#define int long long
#define debug(x) cout<<"debug:"<<x<<endl
using namespace std;
inline int read(){
    int q=0,f=1;char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') f=-1;ch = getchar();
    }
    while(isdigit(ch)){
        q=q*10+ch-'0';ch=getchar();
    }
    return q*f;
}
const int maxn = 300010*2;
const int inf = 0x3f3f3f3f;
int n,m;
int cnt;
int idx;
int rt[maxn];
int size;
int ans;

int head[maxn];
int nxt[maxn];
int ver[maxn];
int w[maxn];

int siz[maxn];
int fa[maxn];
int top[maxn];
int dfn[maxn];
int Last[maxn];
int root;

inline void add(int u,int v,int wi){
    ver[++cnt] = v;
    nxt[cnt] = head[u];head[u] = cnt;
    w[cnt] = wi;
    return;
}

struct node
{
    int v;
    int id;
}a[maxn];

inline bool operator < (node l,node r){
    return l.v == r.v ? l.id < r.id:l.v < r.v;
}

int dep[maxn];
int Dep[maxn];
#define travel(x) for(int i = head[x];i;i=nxt[i])
inline void dfs1(int x,int f){
    siz[x] = 1;
    fa[x] = f;
    travel(x){
        int y = ver[i];
        if(y != f){
            dep[y] = dep[x] + w[i];
            Last[y] = w[i];
            dfs1(y,x);
            siz[x] += siz[y];
        }
    }
}
int E[maxn];
inline void dfs2(int x,int f){
    dfn[x] = ++idx;
    E[dfn[x]] = Last[x];
    int mx = 0;
    int tmp = 0;
    travel(x){
        int y = ver[i];
        if(y != f && siz[y] > mx){
            tmp = y;
            mx = siz[y];
        }
    }
    if(!tmp) return;
    top[tmp] = top[x];
    dfs2(tmp,x);
    travel(x){
        int y  = ver[i];
        if(y != f && y != tmp){
            top[y] = y;
            dfs2(y,x);
        }
    }
}
const int maxm = 8e6+10;
int ls[maxm];
int rs[maxm];
int sum[maxm];
int tot[maxm];

inline void modify(int l,int r,int L,int R,int &p,int v){
    p = ++size;
    ls[p] = ls[v];
    rs[p] = rs[v];
    sum[p] = sum[v];
    tot[p] = tot[v];
    if(l == L && r == R){
        ++tot[p];
        return;
    }
    sum[p] += E[r] - E[l - 1];
    int mid = (L + R) >> 1;
    if(r <= mid){
        modify(l,r,L,mid,ls[p],ls[v]);
    }
    else if(mid +1 <= l){
        modify(l,r,mid+1,R,rs[p],rs[v]);
    }
    else {
        modify(l,mid,L,mid,ls[p],ls[v]);
        modify(mid+1,r,mid+1,R,rs[p],rs[v]);
    }
}

inline int get_ans(int l,int r,int L,int R,int p){
    int res = (E[r] - E[l - 1])*tot[p];
    if(l == L && r == R){
        return res + sum[p];
    }
    int mid = (L + R) >> 1;
    if(r <= mid){
        return res + get_ans(l,r,L,mid,ls[p]);
    }
    else if(mid + 1 <= l){
        return res + get_ans(l,r,mid+1,R,rs[p]);
    }
    else{
        return res + get_ans(l,mid,L,mid,ls[p]) + get_ans(mid+1,r,mid+1,R,rs[p]);
    }
}

inline int get_rt(int p){
    while(p){
        modify(dfn[top[p]],dfn[p],1,n,root,root);

        p = fa[top[p]];
    }
    return root;
}
inline int query(int Rt,int p){
    int res = 0;
    while(p){
        res += get_ans(dfn[top[p]],dfn[p],1,n,Rt);
        //debug(res);
        p = fa[top[p]];
    }
    return res;
}
int A;
inline void solve()
{
    int x,y,z;
    n = read(),m = read(),A = read();
    for(int i = 1;i <= n; ++i){
        a[i].v = read();
        a[i].id = i;
    }
    sort(a+1,a+n+1);
    for(int i = 1;i < n; ++i){
        x = read(),y = read(),z = read();
        add(x,y,z);
        add(y,x,z);
    }
    dfs1(1,0),top[1] = 1;
    dfs2(1,0);
    for(int i = 1;i <= n; ++i){
        E[i] += E[i - 1];
        Dep[i] = Dep[i - 1] + dep[a[i].id];
        ///debug(Dep[i]);
    }
    for(int i = 1;i <= n; ++i){
        rt[i] = get_rt(a[i].id);
        //debug(rt[i]);
    }
//  for(int i = 1;i <= n; ++i)
//  {
//      debug(a[i].v);
//      debug(a[i].id);
//  }
//debug(ans);
    while(m--){
        z = read(),x = read(),y = read();
//      debug(x);
//      debug(y);
        x = (1ll * x + ans)%A;
        y = (1ll * y + ans) % A;
//      debug(x);
//      debug(y);
        if(x > y){
            swap(x,y);
        }
        x=lower_bound(a+1,a+1+n,(node){x,0})- a;
        y=upper_bound(a+1,a+1+n,(node){y,inf})-a-1;

        ans = (y - x + 1)*dep[z]+Dep[y] - Dep[x - 1];
        //debug(ans);
        ans -= 2ll*(query(rt[y],z) - query(rt[x - 1],z));
        //debug(ans);
        printf("%lld\n",ans);
    }
    return;
}

signed main(){solve();return 0;}

猜你喜欢

转载自www.cnblogs.com/akoasm/p/9419298.html
今日推荐