UOJ 58 [WC2013]糖果公园

树上莫队

题解详见VFK大爷的 :
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/

orz vfleaking orz vfleaking orz vfleaking orz vfleaking

这题在本机对拍的时候,忘记在分块里面初始化1,导致所有节点都没有进行分块操作。结果自己拍大数据跑的贼快,大点都只要一秒不到???(可能是因为数据随机?原因成谜。。。)然后非常喜悦 地交上去就T光光了。

真是一段有趣的经历- -

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define reg register
#define N 100005
#define SIZE 2154
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1<<23, stdin), S == T) ? 0 : *S++)
using namespace std;
char B[1<<23], *S = B, *T = B;
bool vis[N];
ll ans, print[N], v[N];
int bin[20], col[N], w[N], last[N], que[N], belong[N], siz[N], block, fa[N][20], dep[N], tot[N];
struct edge{int next,to;}e[N<<1];int ecnt;
struct query{int x, y, t, id;}q[N];int qcnt;
struct change{int x, from, to;}c[N];int ccnt;
int in()
{
    reg int r = 0;
    reg char c = getc();
    while(c<'0'||c>'9')c=getc();
    while(c>='0'&&c<='9')r=r*10+c-'0',c=getc();
    return r;
}
bool cmp(query a, query b)
{
    if(belong[a.x]==belong[b.x] && belong[a.y]==belong[b.y])return a.t<b.t;
    else if(belong[a.x]==belong[b.x])return belong[a.y]<belong[b.y];
    else return belong[a.x]<belong[b.x];
}
void addedge(int a, int b)
{
    e[++ecnt]=(edge){last[a],b};
    last[a]=ecnt;
} 
void addnode(int x, int f)
{
    if(siz[belong[f]]<SIZE)
        belong[x]=belong[f];
    else
        belong[x]=++block;
    siz[belong[x]]++;
}
void makeblock()
{
    que[0]=belong[1]=siz[1]=block=1;
    for(int head=0, tail=1; head<tail; head++)
    {
        int x=que[head];
        for(int i = last[x]; i; i=e[i].next)
        {
            int y=e[i].to;
            if(belong[y])continue;
            que[tail++]=y;
            addnode(y,x);
        }
    }
}
void dfs(int x)
{
    dep[x]=dep[fa[x][0]]+1;
    for(int i = 1; bin[i]<=dep[x]; i++)
        fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i = last[x]; i; i=e[i].next)
    {
        int y=e[i].to;
        if(y==fa[x][0])continue;
        fa[y][0]=x;
        dfs(y);
    }
}
void reverse(int x)
{
    if(vis[x])ans-=w[tot[col[x]]]*v[col[x]], tot[col[x]]--;
    else tot[col[x]]++, ans+=w[tot[col[x]]]*v[col[x]];
    vis[x]=!vis[x];
}
void make(int x, int y)
{
    while(x!=y)
    {
        if(dep[x]>dep[y])reverse(x), x=fa[x][0];
        else reverse(y), y=fa[y][0];
    }
}
void turn(int x, int y)
{
    if(vis[x])
    {
        ans-=w[tot[col[x]]]*v[col[x]];
        tot[col[x]]--;
        tot[y]++;
        ans+=w[tot[y]]*v[y]; 
    }
    col[x]=y;
}
int lca(int x, int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int t = dep[x]-dep[y];
    for(int i = 0; bin[i]<=t; i++)
        if(t&bin[i])
            x=fa[x][i];
    for(int i = 19; i>=0; i--)
    {
        if(fa[x][i]!=fa[y][i])
            x=fa[x][i], y=fa[y][i];
    }
    return x==y?x:fa[x][0];
}
int main()
{
    int n=in(), m=in(), Q=in();
    bin[0]=1;
    for(int i = 1; i < 20; i++)
        bin[i]=bin[i-1]<<1;
    for(int i = 1; i <= m; i++)
        v[i]=in();
    for(int i = 1; i <= n; i++)
        w[i]=in();
    for(int i = 1, a, b; i < n; i++)
    {
        a=in(); b=in();
        addedge(a,b);
        addedge(b,a);
    }
    for(int i = 1; i <= n; i++)
        col[i]=in();
    makeblock();
    dfs(1);
    for(int i = 1; i <= Q; i++)
    {
        int op=in(), x=in(), y=in();
        if(op==0)
        {
            c[++ccnt]=(change){x,col[x],y};
            col[x]=y;
        }
        else
        {
            if(x>y)swap(x,y);
            q[++qcnt]=(query){x,y,ccnt,qcnt};
        }
    }
    sort(q+1,q+1+qcnt,cmp);
    make(q[1].x,q[1].y);
    for(;ccnt<q[1].t;ccnt++)
        turn(c[ccnt+1].x, c[ccnt+1].to);
    for(;ccnt>q[1].t;ccnt--)
        turn(c[ccnt].x, c[ccnt].from);
    int t=lca(q[1].x,q[1].y);
    reverse(t); 
    print[q[1].id]=ans;
    reverse(t);
    for(int i = 2; i <= qcnt; i++)
    {
        for(;ccnt<q[i].t;ccnt++)
            turn(c[ccnt+1].x, c[ccnt+1].to);
        for(;ccnt>q[i].t;ccnt--)
            turn(c[ccnt].x, c[ccnt].from);
        make(q[i].x,q[i-1].x);
        make(q[i].y,q[i-1].y);
        int temp=lca(q[i].x,q[i].y);
        reverse(temp);
        print[q[i].id]=ans;
        reverse(temp);
    }
    for(int i = 1; i <= qcnt; i++)
        printf("%lld\n",print[i]);
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值