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

原文地址:https://www.cnblogs.com/mhy12345/p/4304353.html