列表

详情


NC14692. 追求者

描述

cc是个可爱的女孩子,可爱的女孩子自然不缺人追了,某一天dd心血来潮想把追cc的N个人进行某种奇怪的排列,他给每个人分了一个id(从1开始),画在纸上,并且在其中一些点之间连了线,并且给这些线的加了权值,使得所有人组成一棵树。
然后,他想找出某个属性便于将所有人分开...在分析了所有人的各种属性之后,他发现,每个人看过的动漫数量ai是不一样的!而且恰好看过最多动漫的那个人只看过N部,而最少的看过一部。
刚上完数据结构课的cc发现dd居然在做这么无聊的一件事,于是她决定出几个问题考考dd,她随机给出三个整数l,r,p,希望dd可以告诉她所有id为ai(i∈[l,r])的点到p点的距离总和。
dd觉得这种问题简直是在侮辱他的智商,拍着胸脯立下了flag,不但能解决这个问题,甚至在中途交换某两个编号相邻的看动漫数量ai之后他依旧能很快的给出答案....
然而当cc不停的提问的时候,dd发现随着ai的交换,他的脑子越来越乱了...但是flag已经立下了,所以你可以帮他解决这个问题吗?

输入描述

第一行包含两个整数N,Q表示总人数N以及询问数Q
接下去的一行包含N个整数的,表示每个人看的动漫数量a1,a2,...an,是1,2,...n的排列
接下去的N-1行每行包含三个整数x,y,z表示点x与点y相连,连线权值为z,数据保证构成一棵树
接下去的每次询问包含两行
第一行为o=1或2表示询问类型
若o=1,接下去一行包含三个整数l,r,p,如题中所述
若o=2,接下去一行包含一个整数x,表示交换ax与ax+1
输入保证1<=l,r,n<=n && l<=r, 1<=x<n
1<=n,q<=200000

输出描述

对每次o=1的询问输出结果ans。

示例1

输入:

5 4
4 5 1 3 2
4 2 4
1 3 9
4 1 4
4 5 2
1
1 5 4
1
1 3 3
2
3
2
2

输出:

23
37

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 3046ms, 内存消耗: 180044K, 提交时间: 2017-12-18 16:29:52

#include <bits/stdc++.h>
#define LL long long
using namespace std;
int L,R,X,Y,Z,U,V,t,op,n,m,aa[200005],on[200005],F[200005][20],G[200005][20],H[200005],zz;
vector <int> a[200005],b[200005];
LL W[200005][20],h[200005],ans;
struct O{int x; LL s;};
vector <O> P[400005];
bool operator<(O a,O b){return a.x<b.x;}
void QH(int x,int fa){
    int z=-1,y;
    for (int i=0;i<a[x].size();++i)
    if (a[x][i]!=fa){
        y=a[x][i]; QH(y,x);
        for (int j=0;j<20;++j){
            if (F[y][j]&F[x][j]) z=max(z,j);
            F[x][j]|=F[y][j];
        }
    }
    for (++z;F[x][z];++z); F[x][z]=1;
    H[x]=z; for (--z;~z;--z) F[x][z]=0;
    zz=max(zz,H[x]);
}
void dfs(int x,int y){
    F[x][Z]=U; W[x][Z]=h[x]; G[x][Z]=V;
    P[U].push_back((O){on[x],h[x]});
    P[V].push_back((O){on[x],h[x]});
    for (int i=0;i<a[x].size();++i)
    if (a[x][i]!=y&&H[a[x][i]]<Z){
        h[a[x][i]]=h[x]+b[x][i];
        dfs(a[x][i],x);
    }
}
LL qiu(int u,LL w){
    int p=lower_bound(P[u].begin(),P[u].end(),(O){L,0})-P[u].begin()-1,
        q=upper_bound(P[u].begin(),P[u].end(),(O){R,0})-P[u].begin()-1;
    return (q>=0?P[u][q].s:0)-(p>=0?P[u][p].s:0)+w*(q-p);
}
void mody(int u,int v){
    if (u==v&&u){
        O x={on[X],0};
        int t=lower_bound(P[u].begin(),P[u].end(),x)-P[u].begin();
        LL s=t?P[u][t-1].s:0;
        P[u][t+1].s-=P[u][t].s; P[u][t].s-=s;
        swap(P[u][t].s,P[u][t+1].s);
        P[u][t].s+=s; P[u][t+1].s+=P[u][t].s;
        return;
    }
    if (u){
        O x={on[X],0};
        int t=lower_bound(P[u].begin(),P[u].end(),x)-P[u].begin();
        ++P[u][t].x;
    }
    if (v){
        O x={on[Y],0};
        int t=lower_bound(P[v].begin(),P[v].end(),x)-P[v].begin();
        --P[v][t].x;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i) scanf("%d",&aa[i]),on[aa[i]]=i;
    for (int i=1;i<n;++i){
        scanf("%d%d%d",&X,&Y,&Z);
        a[X].push_back(Y); b[X].push_back(Z);
        a[Y].push_back(X); b[Y].push_back(Z);
    }
    QH(1,0); memset(F,0,sizeof F);
    for (int i=1;i<=n;++i){
        X=aa[i]; Z=H[X]; U=++t; h[X]=0;
        P[U].push_back((O){on[X],0}); F[X][Z]=U;
        for (int j=0;j<a[X].size();++j)
        if (H[a[X][j]]<Z){
            h[a[X][j]]=b[X][j];
            V=++t; dfs(a[X][j],X);
            sort(P[V].begin(),P[V].end());
            for (int k=1;k<P[V].size();++k)
                P[V][k].s+=P[V][k-1].s;
        }
        sort(P[U].begin(),P[U].end());
        for (int k=1;k<P[U].size();++k)
            P[U][k].s+=P[U][k-1].s;
    }
    while (m--){
        scanf("%d",&op);
        if (op==1){
            scanf("%d%d%d",&L,&R,&X); ans=0;
            for (int i=H[X];i<=zz;++i)
            ans+=qiu(F[X][i],W[X][i])-qiu(G[X][i],W[X][i]);
            printf("%lld\n",ans);
        }else{
            scanf("%d",&Z); X=aa[Z]; Y=aa[Z+1];
            swap(aa[Z],aa[Z+1]);
            for (int i=0;i<=zz;++i){
                mody(F[X][i],F[Y][i]);
                mody(G[X][i],G[Y][i]);
            }
            swap(on[X],on[Y]);
        }
    }
    return 0;
}

上一题