题意:给定一棵n个点带边权的树,定义每条路径的值为路径上边权的异或和

如果一条路径的值为0,其对答案的贡献为所有包含这条路径的路径条数

求答案膜1e9+7

n<=1e5,0<=边权<=1e18

思路:

做法一:点分治

参考https://dudulu.net/blog/?p=1654

考场上还剩2小时的时候开的这题,乍一看觉得很可做就是个裸的点分,结果发现自己不会算贡献,场上连样例都没调出来

现在也是写了两天发现不会算贡献,参考了dalao的博客才会

每条路径的权值可以用两个端点分别能扩展的点的个数的乘积来算

预处理一下以1为根每个点的父亲和子树大小

在分治过程中,假设有u->……->pre->v这条路径

对于v这个点:

如果pre=f[v]可扩展的个数就是siz[v]

若果pre!=f[v]可扩展的个数就是n-siz[pre]

对于分治中心u和u的每个直接分支v:

如果u=f[v]可扩展的个数就是n-siz[v]

如果u!=f[v]可扩展的个数就是siz[u]

扔到map里记一下前缀和

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. typedef unsigned int uint;
  5. typedef unsigned long long ull;
  6. typedef pair<int,int> PII;
  7. typedef pair<ll,ll> Pll;
  8. typedef vector<int> VI;
  9. typedef vector<PII> VII;
  10. //typedef pair<ll,ll>P;
  11. #define N 200010
  12. #define M 200010
  13. #define fi first
  14. #define se second
  15. #define MP make_pair
  16. #define pb push_back
  17. #define pi acos(-1)
  18. #define mem(a,b) memset(a,b,sizeof(a))
  19. #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
  20. #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
  21. #define lowbit(x) x&(-x)
  22. #define Rand (rand()*(1<<16)+rand())
  23. #define id(x) ((x)<=B?(x):m-n/(x)+1)
  24. #define ls p<<1
  25. #define rs p<<1|1
  26.  
  27. const ll MOD=1e9+,inv2=(MOD+)/;
  28. double eps=1e-;
  29. ll INF=1e15;
  30. int dx[]={-,,,};
  31. int dy[]={,,-,};
  32.  
  33. struct node
  34. {
  35. int x;
  36. ll y;
  37. }q[N];
  38.  
  39. map<ll,ll>mp1,mp2;
  40. map<ll,ll>::iterator it;
  41. int head[N],vet[N],nxt[N],c[N],flag[N],son[N],
  42. s[N],siz[N],f[N],pre[N],tot,root,sum,n,now;
  43. ll len[N],dis[N],ans;
  44.  
  45. int read()
  46. {
  47. int v=,f=;
  48. char c=getchar();
  49. while(c<||<c) {if(c=='-') f=-; c=getchar();}
  50. while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
  51. return v*f;
  52. }
  53.  
  54. void add(int a,int b,ll c)
  55. {
  56. nxt[++tot]=head[a];
  57. vet[tot]=b;
  58. len[tot]=c;
  59. head[a]=tot;
  60. }
  61.  
  62. void getroot(int u,int fa)
  63. {
  64. son[u]=; c[u]=;
  65. int e=head[u];
  66. while(e)
  67. {
  68. int v=vet[e];
  69. if(v!=fa&&!flag[v])
  70. {
  71. getroot(v,u);
  72. son[u]+=son[v];
  73. c[u]=max(c[u],son[v]);
  74. }
  75. e=nxt[e];
  76. }
  77. c[u]=max(c[u],sum-c[u]);
  78. if(c[u]<c[root]) root=u;
  79. }
  80.  
  81. void dfs(int u,int fa)
  82. {
  83. siz[u]=;
  84. int e=head[u];
  85. while(e)
  86. {
  87. int v=vet[e];
  88. if(v!=fa)
  89. {
  90. f[v]=u;
  91. dfs(v,u);
  92. siz[u]+=siz[v];
  93. }
  94. e=nxt[e];
  95. }
  96. }
  97.  
  98. void getdis(int u,int fa)
  99. {
  100. if(fa==f[u])
  101. {
  102. mp1[dis[u]]=(mp1[dis[u]]+siz[u])%MOD;
  103. if(dis[u]==) ans=(ans+1ll*siz[u]*now%MOD)%MOD;
  104. }
  105. else
  106. {
  107. mp1[dis[u]]=(mp1[dis[u]]+n-siz[fa])%MOD;
  108. if(dis[u]==) ans=(ans+1ll*(n-siz[fa])*now%MOD)%MOD;
  109. }
  110. int e=head[u];
  111. while(e)
  112. {
  113. int v=vet[e];
  114. if(v!=fa&&!flag[v])
  115. {
  116. dis[v]=dis[u]^len[e];
  117. getdis(v,u);
  118. }
  119. e=nxt[e];
  120. }
  121. }
  122.  
  123. void calc(int u)
  124. {
  125. dis[u]=;
  126. int e=head[u];
  127. while(e)
  128. {
  129. int v=vet[e];
  130. if(flag[v])
  131. {
  132. e=nxt[e];
  133. continue;
  134. }
  135. mp1.clear();
  136. if(f[v]==u) now=n-siz[v];
  137. else now=siz[u];
  138. dis[v]=len[e];
  139. getdis(v,u);
  140. it=mp1.begin();
  141. while(it!=mp1.end())
  142. {
  143. ll w=it->fi,t=it->se;
  144. ans=(ans+t*mp2[w]%MOD)%MOD;
  145. it++;
  146. }
  147. it=mp1.begin();
  148. while(it!=mp1.end())
  149. {
  150. ll w=it->fi,t=it->se;
  151. mp2[w]=(mp2[w]+t)%MOD;
  152. it++;
  153. }
  154. e=nxt[e];
  155. }
  156. mp2.clear();
  157. }
  158.  
  159. void solve(int u)
  160. {
  161. flag[u]=;
  162. calc(u);
  163. int e=head[u];
  164. while(e)
  165. {
  166. int v=vet[e];
  167. if(!flag[v])
  168. {
  169. sum=son[v]; root=;
  170. getroot(v,);
  171. solve(root);
  172. }
  173. e=nxt[e];
  174. }
  175. }
  176.  
  177. int main()
  178. {
  179. //freopen("1.in","r",stdin);
  180. //freopen("1.out","w",stdout);
  181. n=read();
  182. rep(i,,n) head[i]=flag[i]=;
  183. tot=;
  184. rep(i,,n)
  185. {
  186. int x=read();
  187. ll y;
  188. scanf("%lld",&y);
  189. add(i,x,y);
  190. add(x,i,y);
  191. }
  192. dfs(,);
  193. sum=n; c[]=n; ans=; root=;
  194. getroot(,);
  195. solve(root);
  196. printf("%lld\n",ans);
  197. return ;
  198. }

做法二:算贡献

预处理出每个点的子树大小和每个点到根的xor和

对于(x,y)这条权值为0的链分两种情况,均在dfs到dfs序靠后的那个点时计算贡献:

1.y在x的子树中,贡献在y时候被算到,贡献为size[y]*(n-size[z]),其中z为x的一个儿子,且y在z的子树中

2.x,y是从他们的lca下来的两条链拼起来的,贡献为size[x]*size[y]

可以看出对于第一种情况,可以用map记一下根到每个点(n-size[z])之和,在切换子树时需要减去(n-size[z])消除贡献

对于第二种情况,记size[u]之和,不需要减去

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. typedef unsigned int uint;
  5. typedef unsigned long long ull;
  6. typedef pair<int,int> PII;
  7. typedef pair<ll,ll> Pll;
  8. typedef vector<int> VI;
  9. typedef vector<PII> VII;
  10. //typedef pair<ll,ll>P;
  11. #define N 200010
  12. #define M 200010
  13. #define fi first
  14. #define se second
  15. #define MP make_pair
  16. #define pb push_back
  17. #define pi acos(-1)
  18. #define mem(a,b) memset(a,b,sizeof(a))
  19. #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
  20. #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
  21. #define lowbit(x) x&(-x)
  22. #define Rand (rand()*(1<<16)+rand())
  23. #define id(x) ((x)<=B?(x):m-n/(x)+1)
  24. #define ls p<<1
  25. #define rs p<<1|1
  26.  
  27. const ll MOD=1e9+,inv2=(MOD+)/;
  28. double eps=1e-;
  29. ll INF=1e15;
  30. int dx[]={-,,,};
  31. int dy[]={,,-,};
  32.  
  33. map<ll,ll>mp;
  34. int head[N],vet[N],nxt[N],s[N],tot,n;
  35. ll a[N],dis[N],ans;
  36.  
  37. int read()
  38. {
  39. int v=,f=;
  40. char c=getchar();
  41. while(c<||<c) {if(c=='-') f=-; c=getchar();}
  42. while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
  43. return v*f;
  44. }
  45.  
  46. void add(int a,int b)
  47. {
  48. nxt[++tot]=head[a];
  49. vet[tot]=b;
  50. head[a]=tot;
  51. }
  52.  
  53. void dfs(int u,int fa)
  54. {
  55. int e=head[u];
  56. s[u]=;
  57. while(e)
  58. {
  59. int v=vet[e];
  60. if(v!=fa)
  61. {
  62. dis[v]=dis[u]^a[v];
  63. dfs(v,u);
  64. s[u]+=s[v];
  65. }
  66. e=nxt[e];
  67. }
  68. }
  69.  
  70. void solve(int u,int fa)
  71. {
  72. ans=(ans+1ll*s[u]*mp[dis[u]]%MOD)%MOD;
  73. int e=head[u];
  74. while(e)
  75. {
  76. int v=vet[e];
  77. if(v!=fa)
  78. {
  79. mp[dis[u]]=(mp[dis[u]]+n-s[v])%MOD;
  80. solve(v,u);
  81. mp[dis[u]]=(mp[dis[u]]+s[v]-n+MOD)%MOD;
  82. }
  83. e=nxt[e];
  84. }
  85. mp[dis[u]]=(mp[dis[u]]+s[u])%MOD;
  86. }
  87.  
  88. int main()
  89. {
  90. //freopen("1.in","r",stdin);
  91. //freopen("1.out","w",stdout);
  92. n=read();
  93. rep(i,,n) head[i]=;
  94. tot=;
  95. rep(i,,n)
  96. {
  97. int x=read();
  98. ll y;
  99. scanf("%lld",&a[i]);
  100. add(x,i);
  101. }
  102. ans=;
  103. dis[]=;
  104. dfs(,);
  105. mp.clear();
  106. solve(,);
  107. printf("%lld\n",ans);
  108. return ;
  109. }

【2019ICPC西安邀请赛】J.And And And(点分治,贡献)的更多相关文章

  1. 2019icpc西安邀请赛 J And And And (树形dp)

    题目链接:https://nanti.jisuanke.com/t/39277 题意:给出一棵有边权的树,求所有简单路径包含异或和为0的简单路径的总数和. 思路: 首先,对于异或为0这一限制,我们通过 ...

  2. 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛

    Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered  ...

  3. 2019ICPC西安邀请赛 - B. Product - 数论

    打印的时候麻烦把:https://blog.csdn.net/skywalkert/article/details/50500009这个打印下来. 求\(\prod\limits_{i=1}^{n} ...

  4. 2019icpc西安邀请赛

    来源:https://www.jisuanke.com/contest/2625?view=challenges 更新中 A.Tasks 直接贪心 代码:听说当时很多队伍提前拆题甚至上机了,所以很多0 ...

  5. 2019ICPC西安邀请赛(计蒜客复现赛)总结

    开始时因为吃饭晚了一刻钟,然后打开比赛.看了眼榜单A题已经过了二十来个队伍了,宝儿就去做A. 传师说最后一题看题目像最短路,于是我就去看M了,宝儿做完之后也来陪我看.M一开始看到时以为是像   POJ ...

  6. 计蒜客 39280.Travel-二分+最短路dijkstra-二分过程中保存结果,因为二分完最后的不一定是结果 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M.) 2019ICPC西安邀请赛现场赛重现赛

    Travel There are nn planets in the MOT galaxy, and each planet has a unique number from 1 \sim n1∼n. ...

  7. 计蒜客 39279.Swap-打表找规律 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest L.) 2019ICPC西安邀请赛现场赛重现赛

    Swap There is a sequence of numbers of length nn, and each number in the sequence is different. Ther ...

  8. 计蒜客 39270.Angel's Journey-简单的计算几何 ((The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.) 2019ICPC西安邀请赛现场赛重现赛

    Angel's Journey “Miyane!” This day Hana asks Miyako for help again. Hana plays the part of angel on ...

  9. 计蒜客 39268.Tasks-签到 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest A.) 2019ICPC西安邀请赛现场赛重现赛

    Tasks It's too late now, but you still have too much work to do. There are nn tasks on your list. Th ...

随机推荐

  1. Docker安装及部署实例.Net Core

    1.什么是Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...

  2. Matplotlib字体大小设置

    参考:https://blog.csdn.net/henkekao/article/details/72871882 ax = plt.subplot(111) # 设置刻度字体大小 plt.xtic ...

  3. 前端005/React生命周期

    ES6中React生命周期 一.React生命周期 React生命周期主要包括三个阶段:初始化阶段.运行中阶段和销毁阶段. 在React不同的生命周期里,会依次触发不同的钩子函数. 二.React的生 ...

  4. Java中的常用类:包装类、String、StringBuffer、StringBuilder、Math、System、Arrays、BigInteger、BigDecimal、Data、Calendar

    一.包装类 √ 二.String类 ★ 三.StringBuffer和StringBuilder类 ★ 四.Math类 五.System类 六.Arrays类 七.BigInteger类和BigDec ...

  5. dp(电梯与楼梯)

    http://codeforces.com/problemset/problem/1249/E E. By Elevator or Stairs? time limit per test 2 seco ...

  6. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  7. Vue基于vuex、axios拦截器实现loading效果及axios的安装配置

    准备 利用vue-cli脚手架创建项目 进入项目安装vuex.axios(npm install vuex,npm install axios) axios配置 项目中安装axios模块(npm in ...

  8. vue-multi-tab--一个让你在SPA里使用多页签的框架页

    介绍 vue-multi-tab 是一套基于 vue 和 element-ui 的 , 实现了 tab-router (一个基于 tab 的路由) 的 单页面, 多页签 应用程序. 我之前写这个项目的 ...

  9. 一、touch.js

    一.touch.js 1.引用链接: <script src="https://cdn.bootcss.com/touchjs/0.2.14/touch.min.js"> ...

  10. Linux下C语言实现ATM取款机,消息队列版本

    链接:https://pan.baidu.com/s/1oBavXBuZul7ZAEBL1eYfRA 提取码:ffhg Mybank ATM取款机实验,消息队列实现本实验用的是Centos71.在服务 ...