zoukankan      html  css  js  c++  java
  • BZOJ3052:[WC2013]糖果公园

    浅谈莫队:https://www.cnblogs.com/AKMer/p/10374756.html

    题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=3052

    把问题搬到欧拉序上来就是裸的带修改莫队了。

    每次加减某种颜色直接加减个数系数乘美味度即可。

    时间复杂度:(O(n^{frac{5}{3}}))

    空间复杂度:(O(n))

    代码如下:

    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
     
    const int maxn=1e5+5;
     
    ll ans;bool vis[maxn];
    int dep[maxn],f[maxn][18];
    int v[maxn],w[maxn],lst[maxn],c[maxn];
    int now[maxn],pre[maxn<<1],son[maxn<<1];
    int n,m,q,block,tot,cnt1,cnt2,cnt,nowl,nowr,T;
    int dfn[maxn<<1],L[maxn],R[maxn],sum[maxn],bel[maxn<<1];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    void add(int a,int b) {
        pre[++tot]=now[a];
        now[a]=tot,son[tot]=b;
    }
     
    void dfs(int fa,int u) {
        dfn[++cnt]=u,L[u]=cnt;
        dep[u]=dep[fa]+1,f[u][0]=fa;
        for(int i=1;i<18;i++)
            f[u][i]=f[f[u][i-1]][i-1];
        for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
            if(v!=fa)dfs(u,v);
        dfn[++cnt]=u,R[u]=cnt;
    }
     
    struct query {
        ll res;
        int l,r,id,tim;
     
        query() {}
     
        query(int _l,int _r,int _id,int _tim) {
            l=_l,r=_r,id=_id,tim=_tim;
        }
     
        bool operator<(const query &a)const {
            if(bel[l]==bel[a.l]&&bel[r]==bel[a.r])return tim<a.tim;
            if(bel[l]==bel[a.l])return bel[l]&1?bel[r]<bel[a.r]:bel[r]>bel[a.r];
            return bel[l]<bel[a.l];
        }
    }Q[maxn];
     
    struct modify {
        int node,id,lst;
     
        modify() {}
     
        modify(int _node,int _id,int _lst) {
            node=_node,id=_id,lst=_lst;
        }
    }C[maxn];
     
    int lca(int u,int v) {
        if(dep[u]<dep[v])swap(u,v);
        for(int i=17;~i;i--)
            if(dep[f[u][i]]>=dep[v])
                u=f[u][i];
        if(u==v)return u;
        for(int i=17;~i;i--)
            if(f[u][i]!=f[v][i])
                u=f[u][i],v=f[v][i];
        return f[u][0];
    }
     
    bool cmp(query a,query b) {
        return a.id<b.id;
    }
     
    void change(int u,int id) {
        if(vis[u]) {
            ans+=1ll*w[++sum[id]]*v[id];
            ans-=1ll*w[sum[c[u]]--]*v[c[u]];
        }
        c[u]=id;
    }
     
    void change(int u) {
        if(!vis[u])ans+=1ll*w[++sum[c[u]]]*v[c[u]];
        else ans-=1ll*w[sum[c[u]]--]*v[c[u]];
        vis[u]^=1;
    }
     
    int main() {
        n=read(),m=read(),q=read();
        block=pow(n<<1,2.0/3);
        for(int i=1;i<=m;i++)v[i]=read();
        for(int i=1;i<=n;i++)w[i]=read();
        for(int i=1;i<n;i++) {
            int a=read(),b=read();
            add(a,b),add(b,a);
        }
        dfs(0,1);
        for(int i=1;i<=n;i++)lst[i]=c[i]=read();
        for(int i=1;i<=n<<1;i++)bel[i]=(i-1)/block+1;
        for(int i=1;i<=q;i++) {
            int opt=read();
            if(opt) {
                int u=read(),v=read();
                if(L[u]>L[v])swap(u,v);
                Q[++cnt1]=query(lca(u,v)==u?L[u]:R[u],L[v],i,cnt2);
            }
            else {
                int node=read(),id=read();
                C[++cnt2]=modify(node,id,lst[node]);
                lst[node]=id;
            }
        }
        sort(Q+1,Q+cnt1+1);
        nowl=1,nowr=0,T=0;
        for(int i=1;i<=cnt1;i++) {
            while(T<Q[i].tim)T++,change(C[T].node,C[T].id);
            while(T>Q[i].tim)change(C[T].node,C[T].lst),T--;
            while(nowl<Q[i].l)change(dfn[nowl++]);
            while(nowl>Q[i].l)change(dfn[--nowl]);
            while(nowr<Q[i].r)change(dfn[++nowr]);
            while(nowr>Q[i].r)change(dfn[nowr--]);
            if(L[dfn[Q[i].l]]==Q[i].l)Q[i].res=ans;
            else {
                int tmp=lca(dfn[Q[i].l],dfn[Q[i].r]);
                change(tmp);Q[i].res=ans;change(tmp);
            }
        }
        sort(Q+1,Q+cnt1+1,cmp);
        for(int i=1;i<=cnt1;i++)
        printf("%lld
    ",Q[i].res);
        return 0;
    }
    
  • 相关阅读:
    Linux查看文件被哪个进程占用
    命令行启动rstudio server
    Spring Boot配置文件及多环境配置
    Spring Boot yml配置文件
    js实现自定义概率抽奖算法
    Flutter之adb: failed to install apk的解决方法
    Flutter之不简单的搜索条
    git操作之commit规范
    Flutter之毛玻璃效果的实现
    固定定位下div水平居中
  • 原文地址:https://www.cnblogs.com/AKMer/p/10382064.html
Copyright © 2011-2022 走看看