zoukankan      html  css  js  c++  java
  • 洛谷P4074 [WC2013]糖果公园(莫队)

    传送门

    总算会树形莫队了……

    上次听说树形莫队是给树分块,实在看不懂。然后用括号序列的方法做总算能弄明白了

    先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下

    拿样例为例,它的括号序列就是$12443321$

    那么我们扩展区间对答案的贡献是可以$O(1)$计算的

    假设扩展出的点的颜色是$c$,那么变化量为$val_c*worth_{cnt_c+1}$

    因为括号序列它在扩展的时候会把子树里的扫两遍,那么就可以把子树中的答案去掉了

    怎么去掉呢?记录一个$vis$然后每次扫到的时候异或一下,看看是否被扫过就行了

    然而有几个问题

    第一,$LCA$不是路径端点的话不会被记入答案

    考虑上面的括号序列,如果要从$4$到$3$那么$2$是不会被计入答案的

    第二,起点不是$LCA$的话不会被记入答案

    考虑上面,$u$被算了两次,刚好把自己给减掉了

    所以上面的两种情况要特判

    然后因为是带修莫队,所以再加上时间这一维

    还有这题细节挺多的……我因为跳时间轴的时候一个地方写错WA了好久……

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cmath>
      7 #define ll long long
      8 using namespace std;
      9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     10 char buf[1<<21],*p1=buf,*p2=buf;
     11 inline int read(){
     12     #define num ch-'0'
     13     char ch;bool flag=0;int res;
     14     while(!isdigit(ch=getc()))
     15     (ch=='-')&&(flag=true);
     16     for(res=num;isdigit(ch=getc());res=res*10+num);
     17     (flag)&&(res=-res);
     18     #undef num
     19     return res;
     20 }
     21 char sr[1<<21],z[30];int C=-1,Z;
     22 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
     23 inline void print(ll x){
     24     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
     25     while(z[++Z]=x%10+48,x/=10);
     26     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
     27 }
     28 const int N=100005;
     29 struct query{
     30     int x,y,l,r,id,t;
     31 }q[N];int q1;
     32 struct change{int x,c;}t[N];int q2;
     33 int n,m,L,R,T,s,Q;ll now,ans[N];
     34 int ver[N<<1],edge[N<<1],head[N],Next[N<<1],top[N],dfn[N],dep[N],sz[N],son[N],lis[N<<1],fa[N],tot,num;
     35 int vis[N],col[N],wor[N],cnt[N],val[N];
     36 inline bool cmp(const query a,const query b){
     37     if(a.l^b.l) return a.l<b.l;
     38     if(a.r^b.r) return a.l&1?a.r<b.r:a.r>b.r;
     39     return (a.l^a.r)&1?a.t<b.t:a.t>b.t;
     40 }
     41 inline void add(int u,int v){
     42     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     43     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
     44 }
     45 void dfs(int u){
     46     dep[u]=dep[fa[u]]+1,sz[u]=1;
     47     for(int i=head[u];i;i=Next[i]){
     48         int v=ver[i];
     49         if(v!=fa[u]){
     50             fa[v]=u,dfs(v),sz[u]+=sz[v];
     51             if(sz[v]>sz[son[u]]) son[u]=v;
     52         }
     53     }
     54 }
     55 void dfs(int u,int t){
     56     top[u]=t,lis[dfn[u]=++num]=u;
     57     if(son[u]) dfs(son[u],t);
     58     for(int i=head[u];i;i=Next[i]){
     59         if(ver[i]!=fa[u]&&ver[i]!=son[u]) dfs(ver[i],ver[i]);
     60     }
     61     lis[++num]=u;
     62 }
     63 inline int LCA(int u,int v){
     64     while(top[u]!=top[v]){
     65         if(dep[top[u]]<dep[top[v]]) swap(u,v);
     66         u=fa[top[u]];
     67     }
     68     return dep[u]<dep[v]?u:v;
     69 }
     70 inline void sol(int x){
     71     int c=col[x];
     72     (vis[x]^=1)?now+=(ll)wor[++cnt[c]]*val[c]:now-=(ll)wor[cnt[c]--]*val[c];
     73 }
     74 inline void mdy(int i){
     75     int u=t[i].x,x=t[i].c,y=col[u];
     76     if(vis[u]) now+=(ll)wor[++cnt[x]]*val[x]-(ll)wor[cnt[y]--]*val[y];
     77     t[i].c=y,col[u]=x;
     78 }
     79 int main(){
     80     n=read(),m=read(),Q=read();
     81     for(int i=1;i<=m;++i) val[i]=read();
     82     for(int i=1;i<=n;++i) wor[i]=read();
     83     for(int i=1;i<n;++i){
     84         int u=read(),v=read();add(u,v);
     85     }
     86     for(int i=1;i<=n;++i) col[i]=read();
     87     dfs(1),dfs(1,1);
     88     while(Q--){
     89         int opt=read(),x=read(),y=read();
     90         if(opt){if(dfn[x]>dfn[y]) swap(x,y);
     91             q[++q1]=(query){x,y,dfn[x],dfn[y],q1,q2};
     92         }
     93         else t[++q2]=(change){x,y};
     94     }
     95     s=pow(n,q2?2.0/3:1.0/2);
     96     for(int i=1;i<=n;++i) q[i].l/=s,q[i].r/=s;
     97     sort(q+1,q+1+q1,cmp),L=dfn[q[1].l],R=L-1,T=0;
     98     for(int i=1;i<=q1;++i){
     99         int u=q[i].x,v=q[i].y;
    100         int l=dfn[u],r=dfn[v],g=q[i].t;
    101         while(L>l) sol(lis[--L]);
    102         while(R<r) sol(lis[++R]);
    103         while(L<l) sol(lis[L++]);
    104         while(R>r) sol(lis[R--]);
    105         while(T<g) mdy(++T);
    106         while(T>g) mdy(T--);
    107         //LCA不是路径端点的话是不会计算的
    108         //出发点u如果不是LCA也是不会计算的
    109         //这两个都要特判 
    110         int p=LCA(u,v);
    111         if(u!=p){sol(u);if(v!=p) sol(p);}
    112         ans[q[i].id]=now;
    113         if(u!=p){sol(u);if(v!=p) sol(p);}
    114     }
    115     for(int i=1;i<=q1;++i) print(ans[i]);
    116     Ot();
    117     return 0;
    118 }
  • 相关阅读:
    list 、set 、map 粗浅性能对比分析
    利用 Windows Azure 实现“云优先”
    利用代码改变世界 #AzureDev
    openssl 加密
    openssl 加密
    tls和ssl
    tls和ssl
    从输入框获取输入,插入到文本框
    从输入框获取输入,插入到文本框
    windows expect-5.21r1b1-setup.exe 下载链接
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9537637.html
Copyright © 2011-2022 走看看