HDU6962:I love tree——题解
https://acm.hdu.edu.cn/showproblem.php?pid=6962
支持树上单点查询和路径修改,每次路径修改时按照路径起点到终点的顺序标号1,2,...,然后分别对这些点权+标号$^2$
SB题我就是调不出来。
退化成序列问题思考,对于一个区间[l,r]的修改,第一个数从x开始(即,l位置上的数要$+x^2$,以此类推),那么可以化为第i个数$+(x+l-i)^2$,不妨令$y=x+l$,即变成$(y-i)^2=y^2-2yi+i^2$,因此线段树分别维护三个值即可。
这题恶心就恶心在强行上树然后树链剖分就需要讨论情况。当然你要想写麻烦点也可以通过什么LCA啊来判断每条链的加减情况。我就不想写麻烦于是开始了漫长的debug时光……
#include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e5+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int to,nxt; }e[N<<1]; struct tree{ ll lazy[3]; }t[N<<2]; int head[N],cnt,tot,n,m,rt; int fa[N],pos[N],idx[N],son[N],size[N],dep[N],top[N]; inline void add(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } void dfs1(int u){ size[u]=1; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(fa[u]==v)continue; fa[v]=u;dep[v]=dep[u]+1; dfs1(v); size[u]+=size[v]; if(!son[u]||size[son[u]]<size[v])son[u]=v; } } void dfs2(int u,int anc){ pos[u]=++tot;idx[tot]=u;top[u]=anc; if(!son[u])return; dfs2(son[u],anc); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } inline void init(){ dep[rt]=1; dfs1(rt); dfs2(rt,rt); } void pushdown(int a,int l,int r){ if(t[a].lazy[2]){ t[a<<1].lazy[0]+=t[a].lazy[0]; t[a<<1|1].lazy[0]+=t[a].lazy[0]; t[a<<1].lazy[1]+=t[a].lazy[1]; t[a<<1|1].lazy[1]+=t[a].lazy[1]; t[a<<1].lazy[2]+=t[a].lazy[2]; t[a<<1|1].lazy[2]+=t[a].lazy[2]; t[a].lazy[0]=0;t[a].lazy[1]=0;t[a].lazy[2]=0; } return; } inline ll query(int a,int l,int r,int x){ if(l==r) return t[a].lazy[0]-t[a].lazy[1]*2*l+t[a].lazy[2]*l*l; int mid=(l+r)>>1;pushdown(a,l,r); if(x<=mid) return query(a<<1,l,mid,x); else return query(a<<1|1,mid+1,r,x); } inline void modify(int a,int l,int r,int l1,int r1,ll v){ if(r1<l||r<l1)return; if(l1<=l&&r<=r1){ t[a].lazy[0]+=v*v; t[a].lazy[1]+=v; t[a].lazy[2]+=1; return; } int mid=(l+r)>>1;pushdown(a,l,r); modify(a<<1,l,mid,l1,r1,v);modify(a<<1|1,mid+1,r,l1,r1,v); } struct rem{ int l,r,op; rem(){} rem(int _l,int _r,int _op){l=_l;r=_r;op=_op;} }tmp[N]; inline void mdf(int x,int y){ int sum=0,o=0,op=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]){ swap(x,y);op^=1; } tmp[++o]=rem(pos[top[x]],pos[x],op);sum+=pos[x]-pos[top[x]]+1; x=fa[top[x]]; } if(dep[x]>dep[y]){ swap(x,y);op^=1; } tmp[++o]=rem(pos[x],pos[y],op);sum+=pos[y]-pos[x]+1; int p1=1,p2=sum+1; for(int i=1;i<o;i++){ if(!tmp[i].op){ modify(1,1,n,tmp[i].l,tmp[i].r,tmp[i].r+p1); p1+=tmp[i].r-tmp[i].l+1; }else{ p2-=tmp[i].r-tmp[i].l+1; modify(1,1,n,tmp[i].l,tmp[i].r,tmp[i].l-p2); } } if(!tmp[o].op){ modify(1,1,n,tmp[o].l,tmp[o].r,tmp[o].l-p1); p1+=tmp[o].r-tmp[o].l+1; }else{ p2-=tmp[o].r-tmp[o].l+1; modify(1,1,n,tmp[o].l,tmp[o].r,tmp[o].r+p2); } } inline ll qry(int x){ return query(1,1,n,pos[x]); } int main(){ n=read(),rt=1; for(int i=1;i<n;i++){ int u=read(),v=read(); add(u,v);add(v,u); } init(); m=read(); for(int i=1;i<=m;i++){ int op=read(); if(op==1){ int x=read(),y=read(); mdf(x,y); } if(op==2){ int x=read(); printf("%lld\n",qry(x)); } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++