zoukankan      html  css  js  c++  java
  • bzoj 3052: [wc2013]糖果公园【树上带修改莫队】

    参考:http://blog.csdn.net/lych_cys/article/details/50845832
    把树变成dfs括号序的形式,注意这个是不包含lca的(除非lca是两点中的一个)
    然后把询问按照所属块一序,r二序,t三序排序(注意a和b数组的同名变量意思不一样),对于每个询问处理修改,时间正流或者逆流,修改答案时用vis数组记录这个位置是否在答案中被统计过来决定加减。对于修改序列的操作,如果他没有被统计在答案里就直接修改,否则修改答案。对lca特殊处理

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=200005;
    int n,m,q,u[N],v[N],w[N],h[N],cnt,c[N],la[N],kuai,f[N],g[N],dfn,bl[N],cnta,cntb;
    int de[N],fa[N],fr[N],si[N],hs[N],rl[N];
    long long ans[N],sum;
    bool vis[N];
    struct qw
    {
    	int ne,to;
    }e[N<<1];
    struct qwe
    {
    	int l,r,t,rl;
    }a[N],b[N];//对于b,l是位置,r是修改为的颜色,t是上一个颜色
    bool cmp(qwe x,qwe y)
    {
    	return bl[x.l]<bl[y.l]||bl[x.l]==bl[y.l]&&bl[x.r]<bl[y.r]||bl[x.l]==bl[y.l]&&bl[x.r]==bl[y.r]&&x.t<y.t;
    }
    int read()
    {
    	int r=0;
    	char p=getchar();
    	while(p>'9'||p<'0')
    		p=getchar();
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r;
    }
    void add(int u,int v)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
    	fa[u]=fat;
    	de[u]=de[fat]+1;
    	si[u]=1;
    	f[u]=++dfn;
    	rl[dfn]=u;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fat)
    		{
    			dfs1(e[i].to,u);
    			si[u]+=si[e[i].to];
    			if(si[e[i].to]>si[hs[u]])
    				hs[u]=e[i].to;
    		}
    	g[u]=++dfn;
    	rl[dfn]=u;
    }
    void dfs2(int u,int top)
    {
    	fr[u]=top;
    	if(!hs[u])
    		return;
    	dfs2(hs[u],top);
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u]&&e[i].to!=hs[u])
    			dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {
        for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
        return de[u]>de[v]?v:u;
    }
    void add(int x)
    {
    	if(vis[x])
    		sum-=(long long)v[c[x]]*w[u[c[x]]--];
    	else
    		sum+=(long long)v[c[x]]*w[++u[c[x]]];
    	vis[x]^=1;
    }
    void change(int x,int y)
    {
    	if(vis[x])
    	{
    		add(x);
    		c[x]=y;
    		add(x);
    	}
    	else
    		c[x]=y;
    }
    int main()
    {
    	n=read(),m=read(),q=read();
    	for(int i=1;i<=m;i++)
    		v[i]=read();
    	for(int i=1;i<=n;i++)
    		w[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read();
    		add(x,y);add(y,x);
    	}
    	for(int i=1;i<=n;i++)
    		c[i]=la[i]=read();
    	kuai=(int)pow(n,2.0/3);
    	dfs1(1,0);
    	dfs2(1,1);
    	for(int i=1;i<=dfn;i++)
    		bl[i]=(i-1)/kuai;
    	while(q--)
    	{
    		int t=read(),l=read(),r=read();
    		if(t==0)
    		{
    			b[++cntb].l=l;
    			b[cntb].t=la[l];
    			la[l]=b[cntb].r=r;
    		}
    		else
    		{
    			if(f[l]>f[r])
    				swap(l,r);
    			a[++cnta].r=f[r];
    			a[cnta].rl=cnta;
    			a[cnta].t=cntb;//cout<<lca(l,r)<<endl;
    			a[cnta].l=(lca(l,r)==l)?f[l]:g[l];
    		}
    	}
    	sort(a+1,a+cnta,cmp);
    	int l=1,r=0,t=1;
    	for(int i=1;i<=cnta;i++)
    	{
    		for(;t<=a[i].t;t++)
    			change(b[t].l,b[t].r);
    		for(;t>a[i].t;t--)
    			change(b[t].l,b[t].t);
    		while(l>a[i].l)
    			add(rl[--l]);
    		while(l<a[i].l)
    			add(rl[l++]);
    		while(r>a[i].r)
    			add(rl[r--]);
    		while(r<a[i].r)
    			add(rl[++r]);
    		int x=rl[l],y=rl[r],tmp=lca(x,y);//cout<<x<<" "<<y<<" "<<tmp<<endl;
    		if(x!=tmp&&y!=tmp)
    		{
    			add(tmp);
    			ans[a[i].rl]=sum;
    			add(tmp);
    		}
    		else
    			ans[a[i].rl]=sum;
    	}
    	for(int i=1;i<=cnta;i++)
    		printf("%lld
    ",ans[i]);
    	return 0;
    }
    /*
    4 3 5
    1 9 2
    7 6 5 1
    2 3
    3 1
    3 4
    1 2 3 2
    1 1 2
    1 4 2
    0 2 1
    1 1 2
    1 4 2
    */
    
  • 相关阅读:
    Objective C中提供了线程同步和异常处理
    iOS singleton单例模式的实现
    转:IOS UITableView中行的操作
    Javascript 函数
    ios category类别的使用
    vmware Ubuntu非法关机后启动不起来
    C++ Socket编程步骤
    C/C++ 笔试、面试题目大汇总(转)
    Linux下基于C/C++的Socket编程基础
    C++经典面试题
  • 原文地址:https://www.cnblogs.com/lokiii/p/8267245.html
Copyright © 2011-2022 走看看