zoukankan      html  css  js  c++  java
  • bzoj 3052: [wc2013]糖果公园 带修改莫队

    3052: [wc2013]糖果公园

    Time Limit: 250 Sec  Memory Limit: 512 MB
    Submit: 506  Solved: 189
    [Submit][Status]

    Description

    Input

    Output

    Sample Input

    Sample Input

     

    Sample Output

    84
    131
    27
    84

    HINT

      本来这道题想到了莫队算法,但是看到带修改就直接放弃了。结果看题解才发现带修改居然也能用莫队!!!之所以可以这样用,是因为修改的时间复杂度非常非常低,以至于可以在修改的时间轴上任意跳跃。具体细节自己去看其他题解啦。

      写的有点长,但是跑的还算比较快。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define MAXN 100100
    #define MAXB 2200
    #define MAXQ 100100
    #define MAXV MAXN
    #define MAXE MAXV*2
    typedef long long qword;
    inline int nextInt()
    {
            register int x=0;
            register int ch;
            while (ch=getchar(),ch<'0' || ch>'9');
            while (x=x*10+ch-'0',ch=getchar(),ch<='9' && ch>='0');
            return x;
    }
    int n,m,q,sb;
    struct Edge
    {
            int np;
            Edge *next;
    }E[MAXE],*V[MAXV];
    int tope=-1;
    int que[MAXN];
    void addedge(int x,int y)
    {
            E[++tope].np=y;
            E[tope].next=V[x];
            V[x]=&E[tope];
    }
    int depth[MAXN];
    int pnt[MAXN];
    int top[MAXN],bsiz[MAXN];
    int belong[MAXN];
    int topb=0;
    void bfs1()
    {
            Edge *ne;
            int now;
            int head=-1,tail=0;
            que[0]=1;
            pnt[1]=1;
            belong[1]=++topb;
            top[1]=1;
            bsiz[1]=1;
            depth[1]=1;
            while (head<tail)
            {
                    now=que[++head];
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            if (ne->np==pnt[now])continue;
                            que[++tail]=ne->np;
                            pnt[ne->np]=now;
                            depth[ne->np]=depth[now]+1;
                            if (bsiz[belong[now]]<sb)
                            {
                                    bsiz[belong[now]]++;
                                    belong[ne->np]=belong[now];
                                    top[ne->np]=top[now];
                            }else
                            {
                                    belong[ne->np]=++topb;
                                    bsiz[topb]=1;
                                    top[ne->np]=ne->np;
                            }
                    }
            }
    }
    int jump[20][MAXN];
    void init_lca()
    {
            for (int i=1;i<=n;i++)
                    jump[0][i]=pnt[i];
            for (int j=1;j<20;j++)
                    for (int i=1;i<=n;i++)
                            jump[j][i]=jump[j-1][jump[j-1][i]];
    }
    int lca(int x,int y)
    {
            if (depth[x]<depth[y])swap(x,y);
            int dep=depth[x]-depth[y];
            for (int i=0;i<20;i++)
                    if (dep & (1<<i))
                            x=jump[i][x];
            if (x==y)return x;
            for (int i=19;i>=0;i--)
                    if (jump[i][x]!=jump[i][y])
                            x=jump[i][x],y=jump[i][y];
            return pnt[x];
    }
    int get_dis(int x,int y)
    {
            return depth[x]+depth[y]-2*depth[lca(x,y)];
    }
    struct qur_t
    {
            int s,t,id;
            int upper_pos;
            qword ans;
    }qur[MAXQ];
    int topq=-1;
    bool cmp_qur_block(qur_t a1,qur_t a2)
    {
            if (belong[a1.s]!=belong[a2.s])
                    return belong[a1.s]<belong[a2.s];
            if (belong[a1.t]!=belong[a2.t])
                    return belong[a1.t]<belong[a2.t];
            return a1.id<a2.id;
    }
    bool cmp_qur_id(qur_t a1,qur_t a2)
    {
            return a1.id<a2.id;
    }
    int sweet[MAXN];
    qword suprise[MAXN];
    int candy[MAXN];
    struct mdfy_t
    {
            int pos,cnew,cold,id;
    }mdfy[MAXN];
    int topm=-1;
    struct path
    {
            int s,t,a,ds;
            path(int s,int t):s(s),t(t)
            {
                    a=lca(s,t);
                    ds=depth[s]+depth[t]-2*depth[a];
            }
            path(){}
            bool inside(int x)
            {
                    return get_dis(x,s)+get_dis(x,t)==ds;
            }
            void get_path(int *step,int &tops)
            {
                    tops=-1;
                    for (int x=s;x!=a;x=pnt[x])
                            step[++tops]=x;
                    tops=ds;
                    for (int x=t;x!=a;x=pnt[x])
                            step[tops--]=x;
                    step[tops--]=a;
                    tops=ds;
            }
    };
    int tot[MAXN];
    bool inside[MAXN];
    int step[MAXN],tops;
    int main()
    {
        //    freopen("input.txt","r",stdin);
        //    freopen("output.txt","w",stdout);
            int x,y,z;
            n=nextInt(),m=nextInt(),q=nextInt();
            sb=pow(n,2.0/3);
            for (int i=1;i<=m;i++)
                    sweet[i]=nextInt();
            for (int i=1;i<=n;i++)
                    suprise[i]=nextInt();
            for (int i=1;i<=n;i++)suprise[i]+=suprise[i-1];
            for (int i=1;i<n;i++)
            {
                    x=nextInt(),y=nextInt();
                    addedge(x,y);
                    addedge(y,x);
            }
            for (int i=1;i<=n;i++)
                    candy[i]=nextInt();
            int opt;
            for (int i=1;i<=q;i++)
            {
                    opt=nextInt();
                    if (opt==0)
                    {
                            x=nextInt(),y=nextInt();
                            ++topm;
                            mdfy[topm].pos=x;
                            mdfy[topm].cnew=y;
                            mdfy[topm].cold=candy[x];
                            candy[x]=y;
                            mdfy[topm].id=i;
                    }else
                    {
                            x=nextInt(),y=nextInt();
                            ++topq;
                            qur[topq].s=x;
                            qur[topq].t=y;
                            qur[topq].upper_pos=topm+1;
                            qur[topq].id=i;
                    }
            }
            for (int i=topm;i>=0;i--)
                    candy[mdfy[i].pos]=mdfy[i].cold;
            bfs1();
            init_lca();
            sort(qur,qur+topq+1,cmp_qur_block);
            for (int i=0;i<qur[0].upper_pos;i++)
                    candy[mdfy[i].pos]=mdfy[i].cnew;
            int a;
            a=lca(qur[0].s,qur[0].t);
            qword nsum=0;
            for (x=qur[0].s;x!=a;x=pnt[x])
            {
                    inside[x]=true;
                    tot[candy[x]]++;
                    nsum+=(suprise[tot[candy[x]]]-suprise[tot[candy[x]]-1])*sweet[candy[x]];
            }
            for (y=qur[0].t;;y=pnt[y])
            {
                    inside[y]=true;
                    tot[candy[y]]++;
                    nsum+=(suprise[tot[candy[y]]]-suprise[tot[candy[y]]-1])*sweet[candy[y]];
                    if (y==a)break;
            }
            qur[0].ans=nsum;
            path pnow(qur[0].s,qur[0].t);
            path pwalk;
            for (int i=1;i<=topq;i++)
            {
                    for (int kk=0;kk<2;kk++)
                    {
                            if (kk==0)
                                    pwalk=path(qur[i-1].s,qur[i].s);
                            else
                                    pwalk=path(qur[i-1].t,qur[i].t);
                            pwalk.get_path(step,tops);
                            bool flag=true;
                            for (int j=0;j<=tops+1;j++)
                            {
                                    if (j!=tops+1 && inside[step[j]])
                                    {
                                            inside[step[j]]=false;
                                            tot[candy[step[j]]]--;
                                            nsum+=(suprise[tot[candy[step[j]]]]-suprise[tot[candy[step[j]]]+1])*sweet[candy[step[j]]];
                                    }else
                                    {
                                            if (flag)
                                            {
                                                    inside[step[j-1]]=true;
                                                    tot[candy[step[j-1]]]++;
                                                    nsum+=(suprise[tot[candy[step[j-1]]]]-suprise[tot[candy[step[j-1]]]-1])*sweet[candy[step[j-1]]];
                                                    flag=false;
                                            }
                                            if (j==tops+1)break;
                                            inside[step[j]]=true;
                                            tot[candy[step[j]]]++;
                                            nsum+=(suprise[tot[candy[step[j]]]]-suprise[tot[candy[step[j]]]-1])*sweet[candy[step[j]]];
                                    }
                            }
                    }
                    if (qur[i-1].upper_pos<qur[i].upper_pos)
                    {
                            for (int j=qur[i-1].upper_pos;j<qur[i].upper_pos;j++)
                            {
                                    if (candy[mdfy[j].pos]!=mdfy[j].cold)throw;
                                    candy[mdfy[j].pos]=mdfy[j].cnew;
                                    if (inside[mdfy[j].pos])
                                    {
                                            tot[mdfy[j].cold]--;
                                            nsum+=(suprise[tot[mdfy[j].cold]]-suprise[tot[mdfy[j].cold]+1])*sweet[mdfy[j].cold];
                                            tot[mdfy[j].cnew]++;
                                            nsum+=(suprise[tot[mdfy[j].cnew]]-suprise[tot[mdfy[j].cnew]-1])*sweet[mdfy[j].cnew];
                                    }
                            }
                    }else
                    {
                            for (int j=qur[i-1].upper_pos-1;j>=qur[i].upper_pos;j--)
                            {
                                    if (candy[mdfy[j].pos]!=mdfy[j].cnew)throw;
                                    candy[mdfy[j].pos]=mdfy[j].cold;
                                    if (inside[mdfy[j].pos])
                                    {
                                            tot[mdfy[j].cnew]--;
                                            nsum+=(suprise[tot[mdfy[j].cnew]]-suprise[tot[mdfy[j].cnew]+1])*sweet[mdfy[j].cnew];
                                            tot[mdfy[j].cold]++;
                                            nsum+=(suprise[tot[mdfy[j].cold]]-suprise[tot[mdfy[j].cold]-1])*sweet[mdfy[j].cold];
                                    }
                            }
                    }
                    qur[i].ans=nsum;
            }
            sort(qur,qur+topq+1,cmp_qur_id);
            for (int i=0;i<=topq;i++)
                    printf("%lld
    ",qur[i].ans);
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    整型表示
    有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
    shell排序算法实现
    一些小细节
    wordpress新注册用户或重置密码链接失效
    wordpress访问速度慢
    mysql主从复制
    mysql root密码忘记
    mysql root用户登录后无法查看数据库全部表
    Ansible
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4304353.html
Copyright © 2011-2022 走看看