uoj#58./bzoj3052 【WC2013】糖果公园 //树上带修改莫队

uoj#58. 【WC2013】糖果公园


题意

有一棵N(<=1e5)个点的树,每个点对应M(<=1e5)种糖果中的一种。
一条路径的权值定义为 i(Vitij=1Wj) ,其中i为路径中出现的不同种类糖果,ti为第i种糖果的出现次数,V和W给定。
Q(<=1e5)次操作,每次操作修改一个点对应的糖果种类,或询问路径(u,v)的权值。


题解

半年前写了一半,然而代码弄丢了。
树上莫队和带修改莫队放一起,算是比较模板的题?
跑得太慢了,不好意思写题解,就放个代码吧。


代码

#include<bits/stdc++.h>
#define N 100005
#define L 18
#define Y no[i]
#define X mx[op]
using namespace std;
typedef long long ll;
ll ans[N],s,ss[N];
bool vis[N];
char ch;
inline void rd(int &x)
{
    x=0;
    do ch=getchar();
    while(ch<'0'||ch>'9');
    do x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    while(ch>='0'&&ch<='9');
}
int n,m,q,sqr,tp,mx[N],my[N],pre[N],
ql[N],qr[N],qx[N],no[N],mt,qt,t[N],
V[N],W[N],c[N],b[N],f[N][L],dep[N],
to[N<<1],hd[N<<1],lk[N],cnt;
inline void add(int u,int v)
{to[++cnt]=v,hd[cnt]=lk[u],lk[u]=cnt;}
void dfs(int x)
{
    dep[x]=dep[f[x][0]]+1;
    b[x]=tp++/sqr;
    for(int i=1;f[x][i-1];i++)
    f[x][i]=f[f[x][i-1]][i-1];
    for(int k,i=lk[x];i;i=hd[i])
    if(!dep[k=to[i]])
    f[k][0]=x,dep[k]=dep[x]+1,dfs(k);
}
bool cmp(int x,int y)
{
    return (b[ql[x]]^b[ql[y]])?b[ql[x]]<b[ql[y]]:
    ((b[qr[x]]^b[qr[y]])?b[qr[x]]<b[qr[y]]:qx[x]<qx[y]);
}
inline void ins(int x,int v)
{
    s-=ss[x];
    if(v>0)ss[x]+=(ll)V[x]*W[t[x]+1];
    else ss[x]-=(ll)V[x]*W[t[x]];
    t[x]+=v,s+=ss[x];
}
inline void mdf(int x)
{ins(c[x],(vis[x]^=1)?1:-1);}
inline void trans(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    while(dep[x]>dep[y])
    mdf(x),x=f[x][0];
    while(x^y)mdf(x),mdf(y),x=f[x][0],y=f[y][0];
}
int op,u,v,x,y;
int main()
{
    rd(n),rd(m),rd(q);
    for(int i=1;i<=m;rd(V[i++]));
    for(int i=1;i<=n;rd(W[i++]));
    for(int i=1;i<n;i++)
    rd(u),rd(v),add(u,v),add(v,u);
    for(int i=1;i<=n;rd(c[i++]));
    while(sqr*sqr*sqr<n)sqr++;
    sqr=n/sqr;
    dfs(1),tp=0;
    for(int i=1;i<=q;i++)
    {
        rd(op);
        if(op)
        {
            rd(ql[qt]),rd(qr[qt]);
            if(b[ql[qt]]>b[qr[qt]])
            swap(ql[qt],qr[qt]);
            no[qt]=qt,qx[qt++]=mt;
        }
        else
        rd(u),rd(my[mt]),
        pre[mt]=c[mx[mt]=u],
        c[u]=my[mt++];
    }
    sort(no,no+qt,cmp);
    u=v=1,op=mt;
    for(int i=0;i<qt;i++)
    {
        trans(u,ql[Y]),u=ql[Y];
        trans(v,qr[Y]),v=qr[Y];
        while(op<qx[Y])
        {
            if(vis[X])
            ins(c[X],-1),ins(my[op],1);
            c[X]=my[op],op++;
        }
        while(op>qx[Y])
        {
            op--;
            if(vis[X])
            ins(c[X],-1),ins(pre[op],1);
            c[X]=pre[op];
        }
        x=u,y=v;
        if(dep[y]>dep[x])swap(x,y);
        for(int j=L-1;dep[x]^dep[y];j--)
        if(dep[f[x][j]]>=dep[y])
        x=f[x][j];
        for(int j=L-1;j>=0;j--)
        if(f[x][j]^f[y][j])
        x=f[x][j],y=f[y][j];
        if(x^y)x=f[x][0];
        mdf(x);ans[Y]=s;mdf(x);
    }
    for(int i=0;i<qt;i++)
    printf("%lld\n",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/Starria/article/details/79088950