[LOJ6208]树上询问
题目大意:
有一棵n节点的树,根为1号节点。每个节点有两个权值ki,ti,初始值均为0。
给出三种操作:
1.Add(x,d)操作:将x到根的路径上所有点的ki←ki+d
2.Mul(x,d)操作:将x到根的路径上所有点的ti←ti+d×ki
3.Query(x)操作:询问点x的权值tx
思路:
树链剖分以后用线段树维护。
对于每个结点,我们可以维护3个数a,b,c,表示最后的t为a*b+c。
对于操作1,需要修改a(修改后的ki)和c(修改的数再乘以b就多了,要从c中减去)。
对于操作2,需要修改b。
然后操作3就变成了单点查询。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 inline int getint() { 5 register char ch; 6 register bool neg=false; 7 while(!isdigit(ch=getchar())) if(ch=='-') neg=true; 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return neg?-x:x; 11 } 12 const int N=100001; 13 std::vector<int> e[N]; 14 inline void add_edge(const int &u,const int &v) { 15 e[u].push_back(v); 16 e[v].push_back(u); 17 } 18 int n,par[N],son[N],size[N],dep[N],top[N],id[N]; 19 void dfs1(const int &x,const int &par) { 20 size[x]=1; 21 ::par[x]=par; 22 dep[x]=dep[par]+1; 23 for(unsigned i=0;i<e[x].size();i++) { 24 const int &y=e[x][i]; 25 if(y==par) continue; 26 dfs1(y,x); 27 size[x]+=size[y]; 28 if(size[y]>size[son[x]]) { 29 son[x]=y; 30 } 31 } 32 } 33 void dfs2(const int &x) { 34 id[x]=++id[0]; 35 if(x==son[par[x]]) { 36 top[x]=top[par[x]]; 37 } else { 38 top[x]=x; 39 } 40 if(son[x]) dfs2(son[x]); 41 for(unsigned i=0;i<e[x].size();i++) { 42 const int &y=e[x][i]; 43 if(y==par[x]||y==son[x]) continue; 44 dfs2(y); 45 } 46 } 47 struct Tag { 48 int a,b,c; 49 void operator += (const Tag &another) { 50 c+=another.c-another.a*b; 51 a+=another.a; 52 b+=another.b; 53 } 54 int calc() const { 55 return a*b+c; 56 } 57 }; 58 class SegmentTree { 59 #define _left <<1 60 #define _right <<1|1 61 private: 62 Tag val[N<<2]; 63 void push_down(const int &p) { 64 val[p _left]+=val[p]; 65 val[p _right]+=val[p]; 66 val[p]=(Tag){0,0,0}; 67 } 68 public: 69 void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const Tag &t) { 70 if(b==l&&e==r) { 71 val[p]+=t; 72 return; 73 } 74 push_down(p); 75 const int mid=(b+e)>>1; 76 if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),t); 77 if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,t); 78 } 79 int query(const int &p,const int &b,const int &e,const int &x) { 80 if(b==e) { 81 return val[p].calc(); 82 } 83 push_down(p); 84 const int mid=(b+e)>>1; 85 return x<=mid?query(p _left,b,mid,x):query(p _right,mid+1,e,x); 86 } 87 #undef _left 88 #undef _right 89 }; 90 SegmentTree t; 91 inline void modify(int x,const Tag &tag) { 92 for(;top[x];x=par[top[x]]) { 93 t.modify(1,1,n,id[top[x]],id[x],tag); 94 } 95 } 96 inline int query(const int &x) { 97 return t.query(1,1,n,id[x]); 98 } 99 int main() { 100 n=getint(); 101 for(register int i=1;i<n;i++) { 102 add_edge(getint(),getint()); 103 } 104 dfs1(1,0); 105 dfs2(1); 106 for(register int m=getint();m;m--) { 107 const int opt=getint(),x=getint(); 108 if(opt==1) modify(x,(Tag){getint(),0,0}); 109 if(opt==2) modify(x,(Tag){0,getint(),0}); 110 if(opt==3) printf("%d\n",query(x)); 111 } 112 return 0; 113 }