[BZOJ]3052 糖果公园 树上带修改莫队

来源:互联网 发布:金庸群侠传x 原版数据 编辑:程序博客网 时间:2024/04/28 16:24

3052: [wc2013]糖果公园

Time Limit: 200 Sec  Memory Limit: 512 MB
Submit: 1264  Solved: 637
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Input

Sample Output

84
131
27
84

HINT


Source

[Submit][Status][Discuss]


HOME Back

几句闲话

    这道题我很快的写完了但是调了超久,而且这道题200s的限时差点被别人喷成卡时狗...这道题如果T了的话要T三分钟多,想象就可怕,幸好我主要是WA,虽然T了一次快被机房的人喷成翔...狗眼观察法怎么都看不出来哪里错了,后来才发现,long long强转的时候后面被强转的东西不能打括号,不然的话就是先计算括号内的东西,爆了int以后再转long long就无济于事了...

题解

    一开始怎么都不相信是树上带修改莫队,毕竟n的三分之五次方的时间复杂度几乎就是暴力,这种复杂度只是为了卡掉暴力而已...然而题目的200s允许你这样暴力...一直没写过树上莫队,以及带修改莫队,正好这道题树上带修改莫队,一举两得,赶紧学习一波,一下学两个就当自虐了...
    我们可以发现通过括号序列(dfs序的感觉)可以讲两点的简单路径勾勒出来,因为出现两次的在对应括号序列区间我们会把它^掉,就好像()相消一样,一旦异或回0就消除当前点的贡献.将它转化为普通序列之后,就成为一道lca+普通序列带修改莫队了~注意块的大小.
#include<stdio.h>#include<cmath>#include<algorithm>using namespace std;const int maxn=200005;typedef long long dnt;dnt sum,ans[maxn];int num,cnt1,cnt2,idc,indexx,n,m,T,block,opt;int f[maxn],g[maxn],in[maxn],seq[maxn*3],h[maxn],last[maxn],blo[maxn*2],id[maxn*2],cnt[maxn],c[maxn],v[maxn],w[maxn],st[maxn*2][19],vis[maxn];inline int read(){    register int x=0,f=1;    register char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f*=-1;ch=getchar();}    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();    return f*x;}struct query{    int l,r,t,id;}q[maxn],b[maxn];inline bool cmp(query x,query y){      return blo[x.l]<blo[y.l]||blo[x.l]==blo[y.l]&&blo[x.r]<blo[y.r]||blo[x.l]==blo[y.l]&&blo[x.r]==blo[y.r]&&x.t<y.t;  }  struct edge{    int v,nxt;}e[maxn*2]; inline void add(int u,int v){    e[++num].v=v;    e[num].nxt=h[u];    h[u]=num;}void dfs(int u,int fa){    f[u]=++idc,id[idc]=u;    seq[++indexx]=u,in[u]=indexx;    for(int i=h[u];i;i=e[i].nxt){        int v=e[i].v;        if(v==fa) continue;        dfs(v,u);        seq[++indexx]=u;    }    g[u]=++idc,id[idc]=u;}inline void stha(){    for(register int i=1;i<=indexx;i++) st[i][0]=in[seq[i]];    for(int j=1;(1<<j)<indexx;j++)     for(int i=1;i+(1<<j)-1<=indexx;i++)      st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);}inline int query(int L,int R){    if(L>R) swap(L,R);    int len=R-L+1;    int k=0,ans;    while((1<<(k+1))<len) k++;    ans=min(st[L][k],st[R-(1<<k)+1][k]);    return seq[ans];}inline void update(int x){    if(vis[x]) sum-=(dnt)v[c[x]]*w[cnt[c[x]]--];    else sum+=(dnt)v[c[x]]*w[++cnt[c[x]]];    vis[x]^=1;}inline void chg(int x,int y){    if(vis[x]) update(x),c[x]=y,update(x);    else c[x]=y;}int main(){    register int i,l,r,t;    n=read(),m=read(),T=read();    for(i=1;i<=m;i++)  v[i]=read();    for(i=1;i<=n;i++)  w[i]=read();    for(i=1;i<n;i++)   l=read(),r=read(),add(l,r),add(r,l);    for(i=1;i<=n;i++)  last[i]=c[i]=read();    dfs(1,1);    stha();    block=(int)pow(n,2.0/3);    for(i=1;i<=idc;i++)  blo[i]=(i-1)/block;    for(i=1;i<=T;i++){        opt=read(),l=read(),r=read();        if(opt){           if(f[l]>f[r]) swap(l,r);           q[++cnt1].r=f[r],q[cnt1].t=cnt2,q[cnt1].id=cnt1;           q[cnt1].l=(query(in[l],in[r])==l)?f[l]:g[l];           continue;        }        b[++cnt2].l=l,b[cnt2].t=last[l],last[l]=b[cnt2].r=r;    }    l=1,r=0,t=1,sort(q+1,q+cnt1+1,cmp);    for(i=1;i<=cnt1;i++){        for(;t<=q[i].t;t++) chg(b[t].l,b[t].r);        for(;t>q[i].t;t--)  chg(b[t].l,b[t].t);        while(q[i].l<l) update(id[--l]);while(q[i].l>l) update(id[l++]);        while(r>q[i].r) update(id[r--]);while(r<q[i].r) update(id[++r]);        int x=id[l],y=id[r],lca=query(in[x],in[y]);        if(x!=lca&&y!=lca) update(lca),ans[q[i].id]=sum,update(lca);         else ans[q[i].id]=sum;    }    for(i=1;i<=cnt1;i++) printf("%lld\n",ans[i]);}


原创粉丝点击