UOJ#58. 【WC2013】糖果公园

传送门

分析

首先先推荐一篇关于莫队的博客

这个题我们不难看出就是树上带修莫队

一直在犯sb错误,调了好长时间嘤嘤嘤

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define li long long
const int LOG = 20;
int n,m,q,val[100100],w[100100],now[100100],t1,t2,belong[300100];
li ans[100100],Ans;
int pr[100100][23],N,dfn[300100],beg[300100],fin[300100],dep[100100];
int sum[100100],vis[100100],L,R,T;
vector<int>v[100100];
struct node {
    int x,y,t,ano,pl;
};
node d[100100];
struct iint {
    int x,y,la;
};
iint a[100100];
inline void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    for(int i=0;i<v[x].size();++i)
      if(v[x][i]!=fa){
        pr[v[x][i]][0]=x;
        dfs(v[x][i],x);
      }
}
inline void dfs2(int x,int fa){
    dfn[++N]=x;
    for(int i=0;i<v[x].size();++i)
      if(v[x][i]!=fa)dfs2(v[x][i],x);
    dfn[++N]=x;
}
inline int lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=LOG;i>=0;--i)
      if(dep[pr[x][i]]>=dep[y])x=pr[x][i];
    if(x==y)return x;
    for(int i=LOG;i>=0;--i)
      if(pr[x][i]!=pr[y][i])
        x=pr[x][i],y=pr[y][i];
    return pr[x][0];
}
inline bool cmp(const node &x,const node &y){
    if(belong[x.x]==belong[y.x]){
      if(x.y==y.y)return x.t<y.t;
      return x.y<y.y;
    }
    return x.x<y.x;
}
inline void add(int x){
    sum[now[x]]++;
    Ans+=(li)w[sum[now[x]]]*val[now[x]];
}
inline void deal(int x){
    Ans-=(li)w[sum[now[x]]]*val[now[x]];
    sum[now[x]]--;
}
inline void go(int x,int k){
    int u=(k?x:dfn[x]);
    vis[u]^=1;
    if(vis[u])add(u);
      else deal(u);
}
inline void goago(int x){
    int u=a[x].x;
    if(vis[u])deal(u);
    now[u]=a[x].la;
    if(vis[u])add(u);
}
inline void gonxt(int x){
    int u=a[x].x;
    a[x].la=now[u];
    if(vis[u])deal(u);
    now[u]=a[x].y;
    if(vis[u])add(u);
}
inline int ra(){
    int x=0;char s=getchar();
    while(!isdigit(s))s=getchar();
    while(isdigit(s))x=(x<<3)+(x<<1)+(s-'0'),s=getchar();
    return x;
}
int main(){
    int i,j,k,x,y;
    n=ra(),m=ra(),q=ra();
    for(i=1;i<=m;++i)val[i]=ra();
    for(i=1;i<=n;++i)w[i]=ra();
    for(i=1;i<n;++i){
      x=ra(),y=ra();
      v[x].push_back(y);
      v[y].push_back(x);
    }
    for(i=1;i<=n;++i)now[i]=ra();
    for(i=1;i<=q;++i){
      k=ra(),x=ra(),y=ra();
      if(k){
          d[++t1].x=x;
          d[t1].y=y;
          d[t1].t=t2;
          d[t1].pl=t1;
      }else {
          a[++t2].x=x;
          a[t2].y=y;
      }
    }
    pr[1][0]=0;
    dfs(1,0);
    for(i=1;i<=LOG;++i)
      for(j=1;j<=n;++j)
        pr[j][i]=pr[pr[j][i-1]][i-1];
    dfs2(1,0);
    for(i=1;i<=N;++i)
      if(!beg[dfn[i]])beg[dfn[i]]=i;
    for(i=N;i>0;i--)
      if(!fin[dfn[i]])fin[dfn[i]]=i;
    for(i=1;i<=t1;++i){
      x=d[i].x,y=d[i].y;
      if(beg[x]>beg[y])swap(x,y);
      k=lca(x,y);
      if(x==k)d[i].x=min(fin[x],fin[y]),d[i].y=max(fin[y],fin[x]),d[i].ano=-1;
        else d[i].x=beg[x]+1,d[i].y=fin[y]-1,d[i].ano=k;
    }
    double block=pow((double)N,2.0/3);
    int B=block;
    for(i=1;i<=N;++i)
      belong[i]=(i-1)/B+1;
    sort(d+1,d+t1+1,cmp);
    L=1,R=0,T=0;
    for(i=1;i<=t1;++i){
      while(T>d[i].t){
          goago(T);
          T--;
      }
      while(T<d[i].t){
          T++;
          gonxt(T);
      }
      while(R>d[i].y){
          go(R,0);
          R--;
      }
      while(R<d[i].y){
          R++;
          go(R,0);
      }
      while(L>d[i].x){
          L--;
          go(L,0);
      }
      while(L<d[i].x){
          go(L,0);
          L++;
      }
      if(d[i].ano!=-1)go(d[i].ano,1);
      ans[d[i].pl]=Ans;
      if(d[i].ano!=-1)go(d[i].ano,1);
    }
    for(i=1;i<=t1;++i)
      printf("%lld\n",ans[i]);
    return 0;
}
上一篇:p4068 [SDOI2016]数字配对


下一篇:432D Prefixes and Suffixes