BZOJ3052: [wc2013]糖果公园

树上的带修莫队模板

分块用刚才的王室联邦分快法

然后套带修莫队模板

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
typedef long long LL;
using namespace std;
const int N=100000+7;
int n,m,q,cq,cx,mxsz,is[N],now,px,py;
LL sum,ans[N],v[N],w[N],c[N];

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct node{
    int ti,x,y,pp;
    node(){}
    node(int ti,int x,int y,int pp):ti(ti),x(x),y(y),pp(pp){}
}qs[N],cg[N]; 

int ecnt,fir[N],nxt[N*2],to[N*2],f[N][20];
void add(int u,int v) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
}

int sta[N],top,id[N],R[N],dfn[N],dfs_clock,tot;
void dfs(int x,int fa) {
    int bot=top;
    dfn[x]=++dfs_clock;
    f[x][0]=fa; 
    R[x]=R[fa]+1;
    for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
        dfs(to[i],x);
        if(top-bot>=mxsz) {
            ++tot;
            while(top>bot) 
                id[sta[top--]]=tot;
        }
    }
    sta[++top]=x;
} 

bool cmp(const node&A,const node&B) {
    return id[A.x]==id[B.x]?(id[A.y]==id[B.y]?(A.pp<B.pp):id[A.y]<id[B.y]):id[A.x]<id[B.x];
}

void pre() {
    for(int i=1;i<20;i++)
        for(int j=1;j<=n;j++)
            f[j][i]=f[f[j][i-1]][i-1];
}

int lca(int x,int y) {
    if(R[x]<R[y]) swap(x,y);
    for(int i=19;i>=0;i--)
        if(R[f[x][i]]>=R[y])
            x=f[x][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}

int cnt[N],vis[N];
void change(int x,int f) {
    if(f) {
        cnt[c[x]]++;
        sum+=(LL)w[cnt[c[x]]]*v[c[x]];
    }
    else {
        sum-=(LL)w[cnt[c[x]]]*v[c[x]];
        cnt[c[x]]--;
    }
}

void fz(int x,int y) {
    int z=lca(x,y);
    for(int i=x;i!=z;i=f[i][0]) 
        change(i,vis[i]^=1);
    for(int i=y;i!=z;i=f[i][0]) 
        change(i,vis[i]^=1);
} 

int pr[N],ls[N];
void work() {
    sort(qs+1,qs+cq+1,cmp);
    for(int i=1;i<=cx;i++) {
        if(!ls[cg[i].x]) ls[cg[i].x]=c[cg[i].x];
        pr[i]=ls[cg[i].x]; ls[cg[i].x]=cg[i].y;
    }
    int now=0;
    for(int i=1;i<=cq;i++) {
        int x=qs[i].x,y=qs[i].y;
        int z=lca(x,y);
        for(int j=qs[i-1].pp+1;j<=qs[i].pp;j++) {
            if(vis[cg[j].x]) change(cg[j].x,0); 
            c[cg[j].x]=cg[j].y;
            if(vis[cg[j].x]) change(cg[j].x,1); 
        }
        for(int j=qs[i-1].pp;j>qs[i].pp;j--) {
            if(vis[cg[j].x]) change(cg[j].x,0); 
            c[cg[j].x]=pr[j];
            if(vis[cg[j].x]) change(cg[j].x,1); 
        }
        if(i==1) fz(x,y); 
        else {fz(qs[i-1].x,x); fz(qs[i-1].y,y);}
        change(z,vis[z]^=1);
        ans[qs[i].ti]=sum;
        change(z,vis[z]^=1);
    }
    for(int i=1;i<=q;i++) 
        if(is[i]) printf("%lld\n",ans[i]);
}

void init() {
    read(n); read(m); read(q);
    mxsz=pow(n,2.0/3)*0.5;
    for(int i=1;i<=m;i++) read(v[i]);
    for(int i=1;i<=n;i++) read(w[i]);
    for(int i=1;i<n;i++) {
        int u,v;
        read(u); read(v);
        add(u,v);
    }
    dfs(1,0); 
    pre();
    while(top) id[sta[top--]]=tot;
    for(int i=1;i<=n;i++) read(c[i]);
    for(int i=1;i<=q;i++) {
        int o,x,y;
        read(o); read(x); read(y);
        if(o&&dfn[x]>dfn[y]) swap(x,y);
        if(o) qs[++cq]=node(i,x,y,cx),is[i]=1;
        else cg[++cx]=node(i,x,y,0);
    }
}

int main() {
    init();
    work();
    return 0;
}
View Code

 

posted @ 2017-12-11 07:25  啊宸  阅读(135)  评论(0编辑  收藏  举报