[关闭]
@y20070316 2017-04-26T11:32:46.000000Z 字数 2739 阅读 1293

XSY 2139 - 链上求和

题目精选 DFS序 树状数组 分析


题意


分析

首先,我们定义一个点的大小


按照从小到大排序,逐个插入,那么只用考虑之前插入的点对当前点的贡献,然后再考虑当前点对之后的点的贡献即可。

第二部分很方便维护,考虑解决第一部分。

对于每一个点,考虑的贡献。
①当上,设,则贡献为
总和为

②当子树内,设,则贡献为
总和为
我们枚举,维护子树内的和。

③当的子树外,且不在上时,贡献为
总和为
用之前维护的东西求解即可。

代码

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cctype>
  4. #include <algorithm>
  5. #include <vector>
  6. using namespace std;
  7. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  8. #define fore(v,x) for (vector<int>::iterator v=g[x].begin();v!=g[x].end();v++)
  9. #define LL long long
  10. const int N=131072;
  11. const int M=262144;
  12. const int L=(int)1e9+7;
  13. int n,w[N];
  14. vector<int> g[N];
  15. struct Order {
  16. int w,id;
  17. Order(int _w=0,int _id=0):w(_w),id(_id){}
  18. friend int operator < (Order a,Order b) {
  19. if (a.w!=b.w) return a.w<b.w; else return a.id<b.id;
  20. }
  21. }ord[N];
  22. int s[N],e[N],ind;
  23. int pre[N],siz[N];
  24. int ans;
  25. struct Tree {
  26. int c[M];
  27. int lowbit(int i) {
  28. return i&-i;
  29. }
  30. void Add(int x,int ad) {
  31. for (int i=x;i<=ind;i+=lowbit(i))
  32. (c[i]+=ad)%=L;
  33. }
  34. int Query(int x) {
  35. int sum=0;
  36. for (int i=x;i>0;i-=lowbit(i))
  37. (sum+=c[i])%=L;
  38. return sum;
  39. }
  40. }c1,c2,c3;
  41. namespace input {
  42. const int SIZE=1<<16|1;
  43. char buffer[SIZE];
  44. char *head=buffer+SIZE;
  45. const char *tail=head;
  46. char getch(void) {
  47. if (head==tail) {
  48. fread(buffer,1,SIZE,stdin);
  49. head=buffer;
  50. }
  51. return *head++;
  52. }
  53. int rd(void) {
  54. int x=0,f=1; char c=getch();
  55. for (;!isdigit(c);c=getch()) if (c=='-') f=-1;
  56. for (;isdigit(c);c=getch()) x=x*10+c-'0';
  57. return x*f;
  58. }
  59. }
  60. using input::rd;
  61. void DFS(int x) {
  62. s[x]=++ind;
  63. siz[x]=1;
  64. fore(v,x)
  65. if (*v!=pre[x]) {
  66. pre[*v]=x;
  67. DFS(*v);
  68. siz[x]+=siz[*v];
  69. }
  70. e[x]=++ind;
  71. }
  72. int main(void) {
  73. #ifndef ONLINE_JUDGE
  74. freopen("sdchr.in","r",stdin);
  75. freopen("sdchr.out","w",stdout);
  76. #endif
  77. cin>>n;
  78. F(i,1,n-1) {
  79. int u=rd(),v=rd();
  80. g[u].push_back(v),g[v].push_back(u);
  81. }
  82. F(i,1,n) w[i]=rd();
  83. F(i,1,n) ord[i]=Order(w[i],i);
  84. sort(ord+1,ord+n+1);
  85. DFS(1);
  86. F(i,1,n) {
  87. //考虑点i
  88. int s=1;
  89. fore(v,i)
  90. if (*v!=pre[i]) {
  91. (ans+=(LL)w[i]*s%L*siz[*v]%L)%=L;
  92. s+=siz[*v];
  93. }
  94. if (i!=1)
  95. (ans+=(LL)w[i]*s%L*(n-siz[i])%L)%=L;
  96. }
  97. F(i,1,n) {
  98. int x=ord[i].id;
  99. //到根链
  100. (ans+=(LL)w[x]*siz[x]%L*c1.Query(s[x])%L)%=L;
  101. //子树
  102. fore(v,x) if (*v!=pre[x]) {
  103. int t=(c2.Query(e[*v])-c2.Query(s[*v]-1))%L;
  104. (ans+=(LL)w[x]*(n-siz[*v])%L*t%L)%=L;
  105. }
  106. //子树外且非到根链
  107. int t=(((c2.Query(ind)-(c2.Query(e[x])-c2.Query(s[x]-1)))%L)%L-c3.Query(s[pre[x]]))%L;
  108. (ans+=(LL)w[x]*siz[x]%L*t%L)%=L;
  109. fore(v,x) if (*v!=pre[x]) {
  110. c1.Add(s[*v],n-siz[*v]);
  111. c1.Add(e[*v],-(n-siz[*v]));
  112. }
  113. c2.Add(s[x],siz[x]);
  114. c3.Add(s[x],siz[x]);
  115. c3.Add(e[x],-siz[x]);
  116. }
  117. (ans+=L)%=L;
  118. cout<<ans<<endl;
  119. return 0;
  120. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注