zoukankan      html  css  js  c++  java
  • uoj #58. 【WC2013】糖果公园(树上莫队算法+修改操作)

    【题目链接】

        http://uoj.ac/problem/58

    【题意】

        有一棵树,结点有自己的颜色,若干询问:u,v路径上的获益,并提供修改颜色的操作。

        其中获益定义为Vc*W1+Vc*W2+…+Vc*Wcnt,cnt为经过颜色c的次数。

    【思路】

        如果没有修改操作就和 苹果树 这道题一样了。

        加上修改操作,我们可以对每一个修改操作打上一个时间戳,并记录每一个查询最后修改的时间戳。这样在莫队“区间移动”的时候,只需要根据时间戳进行时光逆流或顺流,即加上现在时间内前一个时间没有的修改或消除现在时间内没有前一个时间存在的修改。

        对于一个修改,如果已经打上标记即这时候计入了now,我们应该先把它在路径上取反存在性,修改后再取反一下就又以新的权值回到了路上,就是重新计算一下贡献。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 const int N = 3e5+10;
     15 const int D = 21;
     16 
     17 ll read() {
     18     char c=getchar();
     19     ll f=1,x=0;
     20     while(!isdigit(c)) {
     21         if(c=='-') f=-1; c=getchar();
     22     }
     23     while(isdigit(c))
     24         x=x*10+c-'0',c=getchar();
     25     return x*f;
     26 }
     27 
     28 struct Edge { int v,nxt;
     29 }e[N<<2];
     30 int en=1,front[N];
     31 void adde(int u,int v) 
     32 {
     33     e[++en]=(Edge){v,front[u]}; front[u]=en;
     34 }
     35 
     36 int n,m,B,Q,dfsc,top,Bcnt;
     37 int cnt[N],C[N]; ll now,ans[N],W[N],V[N];
     38 int pos[N],dfn[N],dep[N],fa[N][D],vis[N],st[N],pre[N];
     39 
     40 struct Node
     41 {
     42     int id,u,v,t;
     43     bool operator < (const Node& rhs) const 
     44     {
     45         if(pos[u]==pos[rhs.u]&&pos[v]==pos[rhs.v]) return t<rhs.t;
     46         else if(pos[u]==pos[rhs.u]) return pos[v]<pos[rhs.v];
     47         else return pos[u]<pos[rhs.u];
     48     }
     49 } q[N];
     50 struct opNode { int u,v,pre;
     51 } que[N];
     52 
     53 int qs,cs;
     54 
     55 int dfs(int u)
     56 {
     57     FOR(i,1,D-1)
     58         fa[u][i]=fa[fa[u][i-1]][i-1];
     59     dfn[u]=++dfsc;
     60     int siz=0;
     61     trav(u,i) {
     62         int v=e[i].v;
     63         if(v!=fa[u][0]) {
     64             fa[v][0]=u;
     65             dep[v]=dep[u]+1;
     66             siz+=dfs(v);
     67             if(siz>=B) {
     68                 Bcnt++;
     69                 while(siz--) 
     70                     pos[st[top--]]=Bcnt;
     71             }
     72         }
     73     }
     74     st[++top]=u;
     75     return siz+1;
     76 }
     77 int lca(int u,int v)
     78 {
     79     if(dep[u]<dep[v]) swap(u,v);
     80     int t=dep[u]-dep[v];
     81     FOR(i,0,D-1)
     82         if(t&(1<<i)) u=fa[u][i];
     83     if(u==v) return u;
     84     for(int i=D-1;i>=0;i--)
     85         if(fa[u][i]!=fa[v][i])
     86             u=fa[u][i],v=fa[v][i];
     87     return fa[u][0];
     88 }
     89 void Xor(int u)
     90 {
     91     if(vis[u]) 
     92         vis[u]=0,now-=V[C[u]]*W[cnt[C[u]]--];
     93     else 
     94         vis[u]=1,now+=V[C[u]]*W[++cnt[C[u]]];
     95 }
     96 void upd(int u,int v)
     97 {
     98     if(vis[u]) {
     99         Xor(u); C[u]=v; Xor(u);
    100     }
    101     else 
    102         C[u]=v;
    103 }
    104 void work(int u,int v)
    105 {
    106     while(u!=v) {
    107         if(dep[u]<dep[v]) swap(u,v);
    108         Xor(u); u=fa[u][0];
    109     }
    110 }
    111 
    112 int main()
    113 {
    114 //    freopen("in.in","r",stdin);
    115 //    freopen("out.out","w",stdout);
    116     n=read(),m=read(),Q=read();
    117     B=pow(n,2.0/3)*0.5;
    118     FOR(i,1,m) V[i]=read();
    119     FOR(i,1,n) W[i]=read();
    120     int op,u,v,w;
    121     FOR(i,1,n-1) {
    122         u=read(),v=read();
    123         adde(u,v),adde(v,u);
    124     }
    125     FOR(i,1,n) 
    126         pre[i]=C[i]=read();
    127 
    128     dfs(1);
    129     ++Bcnt;
    130     while(top) pos[st[top--]]=Bcnt;
    131     FOR(i,1,Q) 
    132     {
    133         op=read(),u=read(),v=read();
    134         if(op==0) {
    135             ++cs;
    136             que[cs].u=u,que[cs].v=v;
    137             que[cs].pre=pre[u]; pre[u]=v;
    138         } else {
    139             ++qs;
    140             if(dfn[u]>dfn[v]) swap(u,v);
    141             q[qs].u=u,q[qs].v=v; 
    142             q[qs].id=qs; q[qs].t=cs;
    143         }
    144     }
    145     sort(q+1,q+qs+1);
    146     FOR(i,1,q[1].t) upd(que[i].u,que[i].v);
    147     work(q[1].u,q[1].v);
    148     int lc=lca(q[1].u,q[1].v);
    149     Xor(lc);
    150     ans[q[1].id]=now;
    151     Xor(lc);
    152     FOR(i,2,qs)
    153     {
    154         for(int j=q[i-1].t+1;j<=q[i].t;j++) upd(que[j].u,que[j].v);
    155         for(int j=q[i-1].t;j>q[i].t;j--) upd(que[j].u,que[j].pre);
    156         work(q[i-1].u,q[i].u);
    157         work(q[i-1].v,q[i].v);
    158         int lc=lca(q[i].u,q[i].v);
    159         Xor(lc);
    160         ans[q[i].id]=now;
    161         Xor(lc);
    162     }
    163     FOR(i,1,qs) printf("%lld
    ",ans[i]);
    164     return 0;
    165 }

    P.S.辣鸡错误毁我青春(摔

      说到底还是自己太辣鸡了QAQ

  • 相关阅读:
    gradle文件中自定义字段值在java代码中使用
    Kotlin中,lateinit 和 lazy{} 的区别
    AndroidStudio Terminal的使用
    组件化踩过的坑
    MVP
    关于组件化的思考
    AspectJ使用的遇到的坑
    使用AOP思想无侵入式申请权限,解决组件化中权限问题(一)
    小米造最强超分辨率算法 | Fast, Accurate and Lightweight Super-Resolution with Neural Architecture Search
    新型超分辨率方法:用神经网络迁移参照图像纹理
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5347237.html
Copyright © 2011-2022 走看看