[CF607D]Power Tree

题目大意:
  一棵树初始只有一个编号为$1$的权值为$w_1$的根。$q(q\le2\times10^5)$次操作,每次可以给出$v,w(w<10^9)$,新建一个结点作为$v$的子结点,权值为$w$;或者给出$u$,求出$f(u)$。定义$f(u)=|S|\cdot\sum_{d\in S}d$,其中$S$为$w_u$与其所有子结点$v$的$f(v)$构成的可重集合。

思路:
  首先将树全部建好,用线段树维护DFS序。每次新加结点相当于将这一结点的权值由$0$变为$w$,用线段树计算加上这个点以后的贡献。题目就变成了线段树上单点加、区间乘、区间求和问题。时间复杂度$O(q(\log n+\log w))$,其中$O(\log w)$是求逆元的复杂度。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<forward_list>
  4 using int64=long long;
  5 inline int getint() {
  6     register char ch;
  7     while(!isdigit(ch=getchar()));
  8     register int x=ch^'0';
  9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 10     return x; 
 11 }
 12 constexpr int N=2e5+1,Q=2e5,mod=1e9+7;
 13 int w[N],n,dfn[N],par[N],size[N],s[N];
 14 std::forward_list<int> e[N];
 15 inline void add_edge(const int &u,const int &v) {
 16     e[u].push_front(v);
 17 }
 18 struct Operation {
 19     int type,v,u;
 20 };
 21 Operation o[N];
 22 void exgcd(const int &a,const int &b,int &x,int &y) {
 23     if(!b) {
 24         x=1,y=0;
 25         return;
 26     }
 27     exgcd(b,a%b,y,x);
 28     y-=a/b*x;
 29 }
 30 int inv(const int &x) {
 31     int ret,tmp;
 32     exgcd(x,mod,ret,tmp);
 33     return (ret%mod+mod)%mod;
 34 }
 35 void dfs(const int &x) {
 36     size[x]=1;
 37     dfn[x]=++dfn[0];
 38     for(auto &y:e[x]) {
 39         dfs(y);
 40         size[x]+=size[y];
 41     }
 42 }
 43 class SegmentTree {
 44     #define _left <<1
 45     #define _right <<1|1
 46     private:
 47         int val[N<<2],tag[N<<2];
 48         void push_up(const int &p) {
 49             val[p]=(val[p _left]+val[p _right])%mod;
 50         }
 51         void push_down(const int &p) {
 52             if(tag[p]==1) return;
 53             tag[p _left]=(int64)tag[p _left]*tag[p]%mod;
 54             tag[p _right]=(int64)tag[p _right]*tag[p]%mod;
 55             val[p _left]=(int64)val[p _left]*tag[p]%mod;
 56             val[p _right]=(int64)val[p _right]*tag[p]%mod;
 57             tag[p]=1;
 58         }
 59     public:
 60         void build(const int &p,const int &b,const int &e) {
 61             tag[p]=1;
 62             if(b==e) return;
 63             const int mid=(b+e)>>1;
 64             build(p _left,b,mid);
 65             build(p _right,mid+1,e);
 66         }
 67         void add(const int &p,const int &b,const int &e,const int &x,const int &v) {
 68             (val[p]+=v)%=mod;
 69             if(b==e) return;
 70             push_down(p);
 71             const int mid=(b+e)>>1;
 72             if(x<=mid) add(p _left,b,mid,x,v);
 73             if(x>mid) add(p _right,mid+1,e,x,v);
 74         }
 75         void mul(const int &p,const int &b,const int &e,const int &l,const int &r,const int &v) {
 76             if(b==l&&e==r) {
 77                 val[p]=(int64)val[p]*v%mod;
 78                 tag[p]=(int64)tag[p]*v%mod;
 79                 return;
 80             }
 81             push_down(p);
 82             const int mid=(b+e)>>1;
 83             if(l<=mid) mul(p _left,b,mid,l,std::min(mid,r),v);
 84             if(r>mid) mul(p _right,mid+1,e,std::max(mid+1,l),r,v);
 85             push_up(p);
 86         }
 87         int query(const int &p,const int &b,const int &e,const int &l,const int &r) {
 88             if(b==l&&e==r) {
 89                 return val[p];
 90             }
 91             push_down(p);
 92             int ret=0;
 93             const int mid=(b+e)>>1;
 94             if(l<=mid) (ret+=query(p _left,b,mid,l,std::min(mid,r)))%=mod;
 95             if(r>mid) (ret+=query(p _right,mid+1,e,std::max(mid+1,l),r))%=mod;
 96             return ret;
 97         }
 98     #undef _left
 99     #undef _right
100 };
101 SegmentTree t;
102 int main() {
103     w[n=1]=getint();
104     const int q=getint();
105     for(register int i=0;i<q;i++) {
106         o[i].type=getint();
107         if(o[i].type==1) {
108             o[i].v=par[++n]=getint();
109             add_edge(par[n],n);
110             w[o[i].u=n]=getint();
111         }
112         if(o[i].type==2) {
113             o[i].v=getint();
114         }
115     }
116     dfs(1);
117     s[1]=1;
118     t.build(1,1,n);
119     t.add(1,1,n,1,w[1]);
120     for(register int i=0;i<q;i++) {
121         const int &y=o[i].u,&x=o[i].v;
122         if(o[i].type==1) {
123             t.add(1,1,n,dfn[y],(int64)t.query(1,1,n,dfn[x],dfn[x])*inv(w[x])%mod*w[y]%mod);
124             t.mul(1,1,n,dfn[x],dfn[x]+size[x]-1,(int64)inv(s[x])*(s[x]+1)%mod);
125             s[x]+=s[y]=1;
126         }
127         if(o[i].type==2) {
128             const int ans=t.query(1,1,n,dfn[x],dfn[x]+size[x]-1);
129             if(x==1) {
130                 printf("%d\n",ans);
131                 continue;
132             }
133             printf("%d\n",int((int64)ans*w[par[x]]%mod*inv(t.query(1,1,n,dfn[par[x]],dfn[par[x]]))%mod));
134         }
135     }
136     return 0;
137 }

 

posted @ 2018-05-22 20:06  skylee03  阅读(183)  评论(0编辑  收藏  举报