[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 }

 

posted @ 2018-01-05 15:02  skylee03  阅读(412)  评论(0编辑  收藏  举报