@y20070316
2017-04-26T11:32:46.000000Z
字数 2739
阅读 1293
题目精选 DFS序 树状数组 分析

首先,我们定义一个点的大小。
第二部分很方便维护,考虑解决第一部分。
对于每一个点,考虑对的贡献。
①当在上,设,则贡献为
总和为
②当在子树内,设,则贡献为
总和为
我们枚举,维护子树内的和。
③当在的子树外,且不在上时,贡献为
总和为
用之前维护的东西求解即可。
#include <cstdio>#include <iostream>#include <cctype>#include <algorithm>#include <vector>using namespace std;#define F(i,a,b) for (int i=(a);i<=(b);i++)#define fore(v,x) for (vector<int>::iterator v=g[x].begin();v!=g[x].end();v++)#define LL long longconst int N=131072;const int M=262144;const int L=(int)1e9+7;int n,w[N];vector<int> g[N];struct Order {int w,id;Order(int _w=0,int _id=0):w(_w),id(_id){}friend int operator < (Order a,Order b) {if (a.w!=b.w) return a.w<b.w; else return a.id<b.id;}}ord[N];int s[N],e[N],ind;int pre[N],siz[N];int ans;struct Tree {int c[M];int lowbit(int i) {return i&-i;}void Add(int x,int ad) {for (int i=x;i<=ind;i+=lowbit(i))(c[i]+=ad)%=L;}int Query(int x) {int sum=0;for (int i=x;i>0;i-=lowbit(i))(sum+=c[i])%=L;return sum;}}c1,c2,c3;namespace input {const int SIZE=1<<16|1;char buffer[SIZE];char *head=buffer+SIZE;const char *tail=head;char getch(void) {if (head==tail) {fread(buffer,1,SIZE,stdin);head=buffer;}return *head++;}int rd(void) {int x=0,f=1; char c=getch();for (;!isdigit(c);c=getch()) if (c=='-') f=-1;for (;isdigit(c);c=getch()) x=x*10+c-'0';return x*f;}}using input::rd;void DFS(int x) {s[x]=++ind;siz[x]=1;fore(v,x)if (*v!=pre[x]) {pre[*v]=x;DFS(*v);siz[x]+=siz[*v];}e[x]=++ind;}int main(void) {#ifndef ONLINE_JUDGEfreopen("sdchr.in","r",stdin);freopen("sdchr.out","w",stdout);#endifcin>>n;F(i,1,n-1) {int u=rd(),v=rd();g[u].push_back(v),g[v].push_back(u);}F(i,1,n) w[i]=rd();F(i,1,n) ord[i]=Order(w[i],i);sort(ord+1,ord+n+1);DFS(1);F(i,1,n) {//考虑点iint s=1;fore(v,i)if (*v!=pre[i]) {(ans+=(LL)w[i]*s%L*siz[*v]%L)%=L;s+=siz[*v];}if (i!=1)(ans+=(LL)w[i]*s%L*(n-siz[i])%L)%=L;}F(i,1,n) {int x=ord[i].id;//到根链(ans+=(LL)w[x]*siz[x]%L*c1.Query(s[x])%L)%=L;//子树fore(v,x) if (*v!=pre[x]) {int t=(c2.Query(e[*v])-c2.Query(s[*v]-1))%L;(ans+=(LL)w[x]*(n-siz[*v])%L*t%L)%=L;}//子树外且非到根链int t=(((c2.Query(ind)-(c2.Query(e[x])-c2.Query(s[x]-1)))%L)%L-c3.Query(s[pre[x]]))%L;(ans+=(LL)w[x]*siz[x]%L*t%L)%=L;fore(v,x) if (*v!=pre[x]) {c1.Add(s[*v],n-siz[*v]);c1.Add(e[*v],-(n-siz[*v]));}c2.Add(s[x],siz[x]);c3.Add(s[x],siz[x]);c3.Add(e[x],-siz[x]);}(ans+=L)%=L;cout<<ans<<endl;return 0;}