• ●UOJ58 [WC2013]糖果公园


    题链:

    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
    ",ANS[i]);
    	return 0;	       
    }
    

      

  • 相关阅读:
    CentOS7使用firewalld打开关闭防火墙与端口
    ssh连接卡在【To escape to local shell, press 'Ctrl+Alt+]'.】的解决方法
    本地链路地址
    RIFF和WAVE音频文件格式
    声音分贝的概念,dBSPL.dBm,dBu,dBV,dBFS
    VS中C++ 项目重命名
    FFmpeg学习6:视音频同步
    FFmpeg学习5:多线程播放视音频
    FFmpeg学习4:音频格式转换
    FFmpeg数据结构:AVPacket解析
  • 原文地址:https://www.cnblogs.com/zj75211/p/8552069.html
Copyright © 2020-2023  润新知