洛谷P3676 小清新数据结构题(动态点分治)

题面在这里>>>

解题思路:

开始写了个LCT后来发现是错的QAQ

正解是动态点分治。

对于一个点,其答案就是$\sum_{i=1}^{n}sum_{i}^{2}$

很神奇地构造出这个式子$\sum_{i=1}^{n}sum_{i}*(Sum_{tot}-sum_{i})$

其中Sumtot是一棵树的总权值和。

可以发现它对于一颗树来说是一个定值。

因为它可以理解成一条边两端选点。

将它拆开,就变成了$\sum_{i=1}^{n}{sum_{i}*Sum_{tot}}-\sum_{i=1}^{n}sum_{i}^{2}$

既然整体是定值,不如在根为1的时候构建,然后维护。

然后算前面那个东西就好了。

厉害就厉害在这里,前面那个东西是可以$O(nlog_{2}n)$计算的。

再来构造一次,这个东西将常数项提出去$Sum_{tot}*{\sum_{i=1}^{n}{sum_{i}}}$

显然那个Sumtot是可以$O(1)$维护的。

后面那个呢?

设当前根为$root$

可以发现对于每一个值产生贡献时在且仅在其父及祖先节点处生效。

所以一共生效了$\mathit{deep_{i}+1}$次

所以说如果设边权为1那么$deep_{i}={\mathit{Dis(i,root)}}$

那么原式就成为了${\sum_{i=1}^{n}{val_{i}}}+{\sum_{i=1}^{n}{\mathit{Dis(i,root)}}}$

剩下的部分和幻想乡那道题就一样了。

代码:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 typedef long long lnt;
  5 const int N=200010;
  6 struct pnt{
  7     int hd;
  8     int fa;
  9     int dp;
 10     int wgt;
 11     lnt val;
 12     lnt sum;
 13     lnt Sum;
 14     int eind;
 15     lnt diss;
 16     lnt disf;
 17     bool vis;
 18 }p[N];
 19 struct ent{
 20     int twd;
 21     int lst;
 22 }e[N<<1];
 23 int rt;
 24 int n,m;
 25 int cnt;
 26 int dfn;
 27 int tdn;
 28 int root;
 29 int size;
 30 int maxsize;
 31 int lg[N<<2];
 32 int eula[N<<2][21];
 33 lnt w;
 34 lnt V;
 35 lnt val[N];
 36 void ade(int f,int t)
 37 {
 38     cnt++;
 39     e[cnt].twd=t;
 40     e[cnt].lst=p[f].hd;
 41     p[f].hd=cnt;
 42     return ;
 43 }
 44 void E_dfs(int x,int f)
 45 {
 46     eula[++dfn][0]=x;
 47     p[x].eind=dfn;
 48     p[x].dp=p[f].dp+1;
 49     for(int i=p[x].hd;i;i=e[i].lst)
 50     {
 51         int to=e[i].twd;
 52         if(to==f)
 53             continue;
 54         E_dfs(to,x);
 55         p[x].wgt+=p[to].wgt;
 56         eula[++dfn][0]=x;
 57     }
 58     return ;
 59 }
 60 void Add_dfs(int x,int f)
 61 {
 62     p[x].Sum=p[x].val;
 63     for(int i=p[x].hd;i;i=e[i].lst)
 64     {
 65         int to=e[i].twd;
 66         if(to==f)
 67             continue;
 68         Add_dfs(to,x);
 69         p[x].Sum+=p[to].Sum;
 70     }
 71     V+=p[x].Sum*(w-p[x].Sum);
 72     return ;
 73 }
 74 int Emin(int x,int y)
 75 {
 76     return p[x].dp<p[y].dp?x:y;
 77 }
 78 int Lca(int x,int y)
 79 {
 80     x=p[x].eind;
 81     y=p[y].eind;
 82     if(x>y)
 83         std::swap(x,y);
 84     int l=lg[y-x+1];
 85     return Emin(eula[x][l],eula[y-(1<<l)+1][l]);
 86 }
 87 int Dis(int x,int y)
 88 {
 89     int z=Lca(x,y);
 90     return p[x].dp+p[y].dp-2*p[z].dp;
 91 }
 92 void grc_dfs(int x,int f)
 93 {
 94     p[x].wgt=1;
 95     int maxs=-1;
 96     for(int i=p[x].hd;i;i=e[i].lst)
 97     {
 98         int to=e[i].twd;
 99         if(to==f||p[to].vis)
100             continue;
101         grc_dfs(to,x);
102         p[x].wgt+=p[to].wgt;
103         if(maxs<p[to].wgt)
104             maxs=p[to].wgt;
105     }
106     maxs=std::max(maxs,size-p[x].wgt);
107     if(maxs<maxsize)
108     {
109         maxsize=maxs;
110         root=x;
111     }
112     return ;
113 }
114 void bin_dfs(int x,int f)
115 {
116     p[x].fa=f;
117     p[x].vis=true;
118     int tmp=size;
119     for(int i=p[x].hd;i;i=e[i].lst)
120     {
121         int to=e[i].twd;
122         if(p[to].vis)
123             continue;
124         root=0;
125         if(p[x].wgt<p[to].wgt)
126             size=tmp-p[x].wgt;
127         else
128             size=p[to].wgt;
129         maxsize=0x3f3f3f3f;
130         grc_dfs(to,to);
131         bin_dfs(root,x);
132     }
133     return ;
134 }
135 void update(int x,lnt y)
136 {
137     p[x].sum+=y;
138     for(int i=x;p[i].fa;i=p[i].fa)
139     {
140         lnt tmp=Dis(x,p[i].fa)*y;
141         p[i].disf+=tmp;
142         p[p[i].fa].diss+=tmp;
143         p[p[i].fa].sum+=y;
144     }
145     return ;
146 }
147 lnt Query(int x)
148 {
149     lnt ans=p[x].diss;
150     for(int i=x;p[i].fa;i=p[i].fa)
151     {
152         lnt tmp=Dis(x,p[i].fa);
153         ans+=p[p[i].fa].diss-p[i].disf;
154         ans+=tmp*(p[p[i].fa].sum-p[i].sum);
155     }
156     return ans;
157 }
158 int main()
159 {
160     scanf("%d%d",&n,&m);
161     for(int i=1;i<n;i++)
162     {
163         int a,b;
164         scanf("%d%d",&a,&b);
165         ade(a,b);
166         ade(b,a);
167     }
168     E_dfs(1,1);
169     for(int i=2;i<=dfn;i++)
170         lg[i]=lg[i>>1]+1;
171     for(int i=1;i<=20;i++)
172         for(int j=1;j+(1<<i)-1<=dfn;j++)
173             eula[j][i]=Emin(eula[j][i-1],eula[j+(1<<(i-1))][i-1]);
174     root=0;
175     size=n;
176     maxsize=0x3f3f3f3f;
177     grc_dfs(1,1);
178     rt=root;
179     bin_dfs(root,0);
180     for(int i=1;i<=n;i++)
181     {
182         scanf("%lld",&p[i].val);
183         update(i,p[i].val);
184         w+=p[i].val;
185     }
186     Add_dfs(1,1);
187     while(m--)
188     {
189         int cmd;
190         scanf("%d",&cmd);
191         if(cmd==1)
192         {
193             int x,y;
194             scanf("%d%d",&x,&y);
195             lnt dv=y-p[x].val;
196             update(x,dv);
197             V+=dv*Query(x);
198             w+=dv;
199             p[x].val=y;
200         }else{
201             int x;
202             scanf("%d",&x);
203             lnt ans=-V+w*w;
204             ans+=Query(x)*w;
205             printf("%lld\n",ans);
206         }
207     }
208     return 0;
209 }

 

posted @ 2018-12-22 11:45  Unstoppable728  阅读(270)  评论(0编辑  收藏  举报