●UOJ58 [WC2013]糖果公園
阿新 • • 發佈:2018-03-12
關鍵字 problem blog register OS lan define 大小 etc
題鏈:
http://uoj.ac/problem/58
題解:
樹上帶修莫隊。
每個塊的大小為$n^{\frac{2}{3}}$,在dfs時,把點集分為若幹塊。
然後類似序列帶修莫隊,三個關鍵字:bel[u],bel[v],time來排序,
從上一個詢問(u,v)更新到新的詢問(u‘,v‘)時,
首先把時間弄對,
然後再把u->lca(u,u‘)->u‘(不含lca(u,u‘))這條鏈上的點的信息取反(原來不存在,現在就存在;原來存在,現在就存在)。
同樣對v->lca(v,v‘)->v‘(不含lca(v,v‘))這條鏈上的點的信息取反。
由於沒有考慮到lca(u‘,v‘)的貢獻,所以加上該lca的後,得到當前詢問的答案。
(被洛谷的數據卡的不要不要的,勉強過了UOJ)
代碼:
#include<bits/stdc++.h> #define MAXN 100005 #define rint register int using namespace std; long long ans,ANS[MAXN]; int N,M,Qnt,BLOCK,nowU,nowV,nowT; int candy[MAXN],s[MAXN],V[MAXN],W[MAXN],fa[MAXN][18],bel[MAXN],deep[MAXN],vis[MAXN],now[MAXN]; struct Edge{ int ent; int to[MAXN*2],nxt[MAXN*2],head[MAXN]; Edge(){ent=2;} void Adde(int u,int v){ to[ent]=v; nxt[ent]=head[u]; head[u]=ent++; } }E; struct Query{ int u,v,t,id; bool operator < (const Query &rtm) const{ return bel[u]==bel[rtm.u]?(bel[v]==bel[rtm.v]?t<rtm.t:bel[v]<bel[rtm.v]):bel[u]<bel[rtm.u]; } }Q[MAXN]; struct Change{int p,nc,oc;}C[MAXN]; void read(int &x){ static int sign; static char ch; sign=1; x=0; ch=getchar(); for(;ch<‘0‘||‘9‘<ch;ch=getchar()) if(ch==‘-‘) sign=-1; for(;‘0‘<=ch&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x=x*sign; } void dfs(int u){ static int stk[MAXN],top,bnt; for(rint k=1;k<17;k++) fa[u][k]=fa[fa[u][k-1]][k-1]; for(rint e=E.head[u];e;e=E.nxt[e]){ int v=E.to[e]; if(v==fa[u][0]) continue; fa[v][0]=u; deep[v]=deep[u]+1; dfs(v); if(top>BLOCK){ ++bnt; while(top) bel[stk[top--]]=bnt; } } stk[++top]=u; if(u==1) while(top) bel[stk[top--]]=bnt; } int LCA(int u,int v){ static int d; if(deep[u]>deep[v]) swap(u,v); d=deep[v]-deep[u]; for(rint k=16;k>=0;k--) if(d&(1<<k)) v=fa[v][k]; if(u==v) return u; for(rint k=16;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k]; return fa[u][0]; } void modify(int p){ if(!vis[p]) candy[s[p]]++,ans+=1ll*W[candy[s[p]]]*V[s[p]]; else ans-=1ll*W[candy[s[p]]]*V[s[p]],candy[s[p]]--; vis[p]^=1; } void trans(rint u,rint v){ while(u!=v) deep[u]>=deep[v]?(modify(u),u=fa[u][0]):(modify(v),v=fa[v][0]); } void dotime(int p,int c){ if(vis[p]) modify(p),s[p]=c,modify(p); else s[p]=c; } int main(){ int q,t,lca; read(N); read(M); read(Qnt); BLOCK=pow(N,0.6); for(rint i=1;i<=M;i++) read(V[i]); for(rint i=1;i<=N;i++) read(W[i]); for(rint i=1,a,b;i<N;i++) read(a),read(b),E.Adde(a,b),E.Adde(b,a); for(rint i=1;i<=N;i++) read(s[i]),now[i]=s[i]; deep[1]=1; dfs(1); for(rint i=1,type,x,y;i<=Qnt;i++){ read(type),read(x),read(y); if(type){ if(bel[x]>bel[y]) swap(x,y); ++q; Q[q]=(Query){x,y,t,q}; } else ++t,C[t]=(Change){x,y,now[x]},now[x]=y; } sort(Q+1,Q+q+1); nowU=nowV=1;nowT=0; for(rint i=1;i<=q;i++){ while(nowT<Q[i].t) nowT++,dotime(C[nowT].p,C[nowT].nc); while(nowT>Q[i].t) dotime(C[nowT].p,C[nowT].oc),nowT--; trans(nowU,Q[i].u); trans(nowV,Q[i].v); nowU=Q[i].u; nowV=Q[i].v; lca=LCA(Q[i].u,Q[i].v); modify(lca); ANS[Q[i].id]=ans; modify(lca); } for(int i=1;i<=q;i++) printf("%lld\n",ANS[i]); return 0; }
●UOJ58 [WC2013]糖果公園