山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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\n",ans[i]);
164     return 0;
165 }

 

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

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

 

posted on 2016-04-02 11:15  hahalidaxin  阅读(318)  评论(0编辑  收藏  举报