LibreOJ #6208. 树上询问
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LibreOJ #6208. 树上询问相关的知识,希望对你有一定的参考价值。
内存限制:512 MiB 时间限制:500 ms 标准输入输出
题目类型:传统 评测方式:文本比较
上传者: 匿名
树链剖分+线段树
#include <vector> #include <cstdio> #define N 100005 using namespace std; vector<int>G[N]; struct Segment { int l,r,mid,t,ki,k,flagk,flagt; Segment * ch[2]; Segment () { t=ki=k=flagk=flagt=0; ch[0]=ch[1]=NULL; } }*root=new Segment; int n,m,tim,top[N],siz[N],dep[N],fa[N],belong[N]; void dfs1(int x) { siz[x]=1; dep[x]=dep[fa[x]]+1; for(int i=0;i<G[x].size();++i) { int v=G[x][i]; if(fa[x]==v) continue; fa[v]=x; dfs1(v); siz[x]+=siz[v]; } } void dfs2(int x) { if(!top[x]) top[x]=x; int p=0; belong[x]=++tim; for(int i=0;i<G[x].size();++i) { int v=G[x][i]; if(fa[x]!=v&&siz[p]<siz[v]) p=v; } if(p) top[p]=top[x],dfs2(p); for(int i=0;i<G[x].size();++i) { int v=G[x][i]; if(fa[x]!=v&&v!=p) dfs2(v); } } void build(Segment *&k,int l,int r) { k=new Segment; k->l=l;k->r=r; if(l==r) return; k->mid=(l+r)>>1; build(k->ch[0],l,k->mid); build(k->ch[1],k->mid+1,r); } void pushdown(Segment *&k) { k->ch[0]->t+=k->t+k->flagt*k->ch[0]->k; k->ch[1]->t+=k->t+k->flagt*k->ch[1]->k; k->ch[0]->ki+=k->flagk; k->ch[1]->ki+=k->flagk; k->ch[0]->flagk+=k->flagk; k->ch[1]->flagk+=k->flagk; k->ch[0]->flagt+=k->flagt; k->ch[1]->flagt+=k->flagt; k->flagk=0; k->flagt=0; k->t=0; } void plusk(Segment *&k,int l,int r,int d) { if(k->l==l&&k->r==r) {k->ki+=d;k->k+=d;k->flagk+=d;return;} pushdown(k); if(l>k->mid) plusk(k->ch[1],l,r,d); else if(r<=k->mid) plusk(k->ch[0],l,r,d); else plusk(k->ch[0],l,k->mid,d),plusk(k->ch[1],k->mid+1,r,d); } void plust(Segment *&k,int l,int r,int d) { if(k->l==l&&k->r==r) {k->t+=d*k->ki;k->flagt+=d;return;} pushdown(k); if(l>k->mid) plust(k->ch[1],l,r,d); else if(r<=k->mid) plust(k->ch[0],l,r,d); else plust(k->ch[0],l,k->mid,d),plust(k->ch[1],k->mid+1,r,d); } int query(Segment *&k,int t) { if(k->l==k->r) return k->t; pushdown(k); if(t<=k->mid) return query(k->ch[0],t); else return query(k->ch[1],t); } void solvek(int x,int y,int d) { for(;top[x]!=top[y];x=fa[top[x]]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); plusk(root,belong[top[x]],belong[x],d); } if(dep[x]<dep[y]) swap(x,y); plusk(root,belong[y],belong[x],d); } void solvet(int x,int y,int d) { for(;top[x]!=top[y];x=fa[top[x]]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); plust(root,belong[top[x]],belong[x],d); } if(dep[x]<dep[y]) swap(x,y); plust(root,belong[y],belong[x],d); } int Main() { scanf("%d",&n); for(int u,v,i=1;i<n;++i) { scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs1(1);dfs2(1); build(root,1,n); scanf("%d",&m); for(int opt,x,d;m--;) { scanf("%d%d",&opt,&x); if(opt==1) {scanf("%d",&d);if(d) solvek(1,x,d);} else if(opt==2) {scanf("%d",&d);if(d) solvet(1,x,d);} else printf("%d\\n",query(root,belong[x])); } return 0; } int sb=Main(); int main(int argc,char *argv[]){;}
以上是关于LibreOJ #6208. 树上询问的主要内容,如果未能解决你的问题,请参考以下文章
libreoj #514. 「LibreOJ β Round #2」模拟只会猜题意