zoukankan      html  css  js  c++  java
  • 【题解】2021HDU多校第二场 HDU6962 I love tree

    2021HDU多校第二场I love tree

    题意

    给一颗(n)个点的树,共有(q)次以下类型的操作

    1 x y:将从(x)(y)这条链上的第(k)个点的值加上(k^2)

    2 x:询问(x)点的值

    (1le n,qle 10^5)

    题解

    首先重链剖分将树剖分为(log n)条不相交的链,由于同一条重链上点的(dfn)是连续的,所以我们可以维护每一条链上以(dfn)为自变量的二次函数的和(关于维护二次函数的和的更详细的解释可以参考这篇博客)。对于某一条重链,其(dfn)最小为(dfnl),最大为(dfnr),假设某次1操作覆盖到了它,则相当于在([dfnl,dfnr])这个区间上添加了一段二次函数(以(dfn)为自变量)。每次2操作相当于查询x所在的链上所有二次函数在(dfn[x])处的值的和。由于加上的二次函数可以表示为((x-h)^2=x^2-2hx+h^2),所以我们维护(x^2,x,1)前的系数即可。

    具体地,对于每次1操作:

    (x ightarrow lca)方向上:对于一条重链上点(nx)到点(ny(dep_{nx}<dep_{ny}即id_{nx}<id_{ny}))的一段,则相当于在([id_{nx},id_{ny}])这个连续区间上添加了一个二次函数((X-(dis(x,nx)+1+id_{nx}))^2)

    (lca ightarrow y)方向上:对于一条重链上点(nx)到点(ny(dep_{nx}<dep_{ny}即id_{nx}<id_{ny}))的一段,则相当于在([id_{nx},id_{ny}])这个连续区间上添加了一个二次函数((X-(id_{nx}-(dis(nx,x)+1))^2)

    #include <bits/stdc++.h>
    #define ls o<<1
    #define rs o<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    using ll=long long ;
    const int N=100005;
    struct edge{
    	int nt,v;
    }e[N<<1];
    int h[N],cnt=0,a[N];
    inline void add(int u,int v){
    	e[++cnt].v=v;e[cnt].nt=h[u];h[u]=cnt;
    }
    ll s[3][N<<2],addv[3][N<<2];
    int x,y,op,z,n,m,r,p,ov[N];
    void pushdown(int k,int o,int l,int r){
    	if(l==r)return ;
    	if(addv[k][o]!=0){
    		s[k][ls]+=(mid-l+1)*addv[k][o];
    		s[k][rs]+=(r-mid)*addv[k][o];
    		addv[k][ls]+=addv[k][o];
    		addv[k][rs]+=addv[k][o];
    		addv[k][o]=0;
    	}
    }
    void pd(int o,int l,int r){
    	pushdown(0,o,l,r);
    	pushdown(1,o,l,r);
    	pushdown(2,o,l,r);
    }
    inline void mt(int o){
    	s[0][o]=s[0][ls]+s[0][rs];
    	s[1][o]=s[1][ls]+s[1][rs];
    	s[2][o]=s[2][ls]+s[2][rs];
    }
    void upd(int o,int l,int r,int x,int y,ll d){
    	if(x<=l&&r<=y){
    		ll na=r-l+1;
    		++addv[0][o];s[0][o]+=na;
    		addv[1][o]-=2ll*d;s[1][o]-=2ll*na*d;
    		addv[2][o]+=d*d;s[2][o]+=1ll*d*d*na;
    	}
    	else{
    		pd(o,l,r);
    		if(x<=mid){upd(ls,l,mid,x,y,d);}
    		if(y>mid){upd(rs,mid+1,r,x,y,d);}
    		mt(o);
    	}
    }
    ll query(int o,int l,int r,int x){
    	if(l==r){return s[0][o]*x*x+s[1][o]*x+s[2][o];}
    	else{
    		pd(o,l,r);
    		if(x<=mid){return query(ls,l,mid,x);}
    		else return query(rs,mid+1,r,x);
    	}
    }
    int na,dep[N],fa[N],son[N],sz[N],id[N],top[N],tot=0;
    void dfs1(int u){
    	na=-1;
    	for(int i=h[u];i;i=e[i].nt){
    		int v=e[i].v;if(v==fa[u])continue;
    		fa[v]=u;sz[v]=1;dep[v]=dep[u]+1;
    		dfs1(v);
    		sz[u]+=sz[v];
    		if(na<sz[v]){na=sz[v];son[u]=v;}
    	}
    }
    void dfs2(int u,int ntop){
    	id[u]=++tot;top[u]=ntop;
    	if(!son[u])return ;
    	dfs2(son[u],ntop);
    	for(int i=h[u];i;i=e[i].nt){
    		int v=e[i].v;if(v==fa[u]||v==son[u])continue;
    		dfs2(v,v);
    	}
    }
    int lca(int x,int y){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		x=fa[top[x]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    
    void chain_add(int x,int y){
    	int lc=lca(x,y);
    	int na=dep[x],nb=na-dep[lc];
    	while(top[x]!=top[y]){
    		if(dep[top[x]]>dep[top[y]]){
    			upd(1,1,n,id[top[x]],id[x],na-dep[top[x]]+1+id[top[x]]);
    			x=fa[top[x]];
    		}
    		else{
    			upd(1,1,n,id[top[y]],id[y],id[top[y]]-(dep[top[y]]-dep[lc]+nb+1));
    			y=fa[top[y]];
    		}
    	}
    	if(dep[x]<dep[y]){
    		upd(1,1,n,id[x],id[y],id[x]-(dep[x]-dep[lc]+nb+1));
    	}
    	else{
    		upd(1,1,n,id[y],id[x],na-dep[y]+1+id[y]);
    	}
    }
    
    void rt(int u){
    	dep[u]=1;sz[u]=1;tot=0;
    	dfs1(u);
    	dfs2(u,u);
    }
    void f1(){
    	int Q;
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int x,y;scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    	}
    	rt(1);
    	scanf("%d",&Q);
    	while(Q--){
    		int op;scanf("%d",&op);
    		if(op==1){
    			int x,y;scanf("%d%d",&x,&y);
    			chain_add(x,y);
    		}
    		else{
    			int x;scanf("%d",&x);
    			printf("%lld
    ",query(1,1,n,id[x]));
    		}
    	}
    }
    int main(){
    	//freopen("6962.in","r",stdin);
    	f1();
    	return 0;
    }
    
  • 相关阅读:
    迅为4412开发板一键烧写QT程序到开发板
    迅为-i.IMX6Q开发板QT系统移植wifi-mt6620(一)
    迅为3399开发板人工智能测试-对象检测
    迅为IMX6ULL开发板搭建 Web 服务器
    迅为IMX6开发板AndroidStudio-ledtest小灯_测试
    迅为3399开发板Android7/Android8修改开机动画
    layui
    MyBatis
    开发过程,一个完整的开发过程需要完成哪些工作?分别由哪些不同的角色来完成这些工作?
    做好测试计划工作的关键是什么?
  • 原文地址:https://www.cnblogs.com/bobh/p/15053034.html
Copyright © 2011-2022 走看看