【GDOI2017模拟二试4.12】树上路径(点剖)
来源:互联网 发布:联通有什么软件 编辑:程序博客网 时间:2024/06/06 06:59
Description
给定一颗n个结点的无根树,树上的每个点有一个非负整数点权,定义一条路径的价值为路径上的点权和-路径的点权最大值。
给定参数p,我们想知道,有多少不同的树上简单路径,满足它的价值恰好是p的倍数。
注意:单点算作一个路径;u ≠ v时,(u,v)和(v,u)只算一次。
Solution
本来是一道很裸的点剖题,但是很久没有打点剖了,并没有去打。
点剖的时候,每个点维护两个值,一个是最大值,还有一个是和。
然后以最大值为第一关键字排序(因为要使得这个最大值一定最大才好统计方案),然后用一个桶记录一下就好了。
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=1e5+7,mxx=1e7+7;int i,j,k,l,t,n,m,ans,p;int first[maxn*2],last[maxn*2],next[maxn*2],num;int a[maxn],z,dian,tot,c[mxx][2],tot1,size[maxn],g[maxn],tim;bool bz[maxn];struct node{ int da,sum;}b[maxn],d[maxn];bool cmp(node x,node y){return x.da<y.da;}void add(int x,int y){last[++num]=y,next[num]=first[x],first[x]=num;}void dfs1(int x,int y){ int i; size[x]=1; rep(i,x)if(!bz[last[i]]&&last[i]!=y)dfs1(last[i],x),size[x]+=size[last[i]];}void dfs2(int x,int y){ int i;bool az=1; rep(i,x)if(!bz[last[i]]&&last[i]!=y){ if(size[last[i]]>dian/2)az=0; dfs2(last[i],x); } if(az&&dian-size[x]<=dian/2)z=x;}void dfs3(int x,int y,int da,int sum){ int i; b[++tot]=(node){da,sum}; rep(i,x)if(last[i]!=y&&!bz[last[i]])dfs3(last[i],x,max(da,g[last[i]]),(sum+a[last[i]])%p);}void fen(int x){ int i; dfs1(x,0);dian=size[x];dfs2(x,0);x=z; tot1=0; bz[x]=1; d[tot=1]=(node){g[x],a[x]}; rep(i,x){ if(bz[last[i]])continue; tot=0; dfs3(last[i],x,max(g[last[i]],g[x]),(a[x]+a[last[i]])%p); fo(j,1,tot)d[++tot1]=b[j]; sort(b+1,b+1+tot,cmp); ++tim; fo(j,1,tot){ k=((b[j].sum-b[j].da)%p+p)%p; if(k)k=p-k; if(c[k][0]!=tim)c[k][0]=tim,c[k][1]=0; ans-=c[k][1]; k=((b[j].sum-a[x])%p+p)%p; if(c[k][0]!=tim)c[k][0]=tim,c[k][1]=0; c[k][1]++; } } sort(d+1,d+1+tot1,cmp); ++tim; fo(i,1,tot1){ k=((d[i].sum-d[i].da)%p+p)%p; if(!k)ans++;else k=p-k; if(c[k][0]!=tim)c[k][0]=tim,c[k][1]=0; ans+=c[k][1]; k=((d[i].sum-a[x])%p+p)%p; if(c[k][0]!=tim)c[k][0]=tim,c[k][1]=0; c[k][1]++; } rep(i,x){ if(!bz[last[i]])fen(last[i]); }}int main(){ freopen("path.in","r",stdin); freopen("path.out","w",stdout); scanf("%d%d",&n,&p); fo(i,1,n-1){ scanf("%d%d",&k,&l); add(k,l),add(l,k); } fo(i,1,n)scanf("%d",&a[i]),g[i]=a[i],a[i]%=p; fen(1); printf("%d\n",ans+n);}
1 0
- 【GDOI2017模拟二试4.12】树上路径(点剖)
- 【jzoj5055】【GDOI2017模拟二试4.12】【树上路径】【点分治】
- 【GDOI2017模拟二试4.12】树上路径
- jzoj 5055. 【GDOI2017模拟二试4.12】树上路径 点分治
- 【JZOJ5055】【GDOI2017模拟二试4.12】树上路径
- 【GDOI2017模拟】树上路径
- 【GDOI2017模拟二试4.12】石子游戏
- 【JZOJ5054】【GDOI2017模拟二试4.12】统计
- 【GDOI2017模拟一试4.11】颜色树(容斥||点剖||DP)
- JZOJ 5052. 【GDOI2017模拟二试4.12】旅游路线
- 【GDOI2017模拟二试4.12】旅游路线(后缀自动机,trie)
- GDOI2017模拟二式
- gdfzoj #510 树上路径(点分治)
- JZOJ 4715 树上路径 (点分)
- 【GDOI2017第三轮模拟day2】树的难题(点剖,树状数组)
- GDOI2017模拟4.12总结
- GDOI2017模拟一试
- jzoj 5052. 【GDOI2017模拟二试4.12】旅游路线 广义后缀自动机
- 递推递归练习--总结
- [BZOJ1430]小猴打架(prufer序列+数学相关)
- 递推递归总结
- 机器学习项目流程及模型评估验证
- 贪心法 2073--> 活动选择问题 SDUT
- 【GDOI2017模拟二试4.12】树上路径(点剖)
- memset函数
- LeetCode 412 Fizz Buzz
- 数据挖掘的学习目标
- LDS 链接脚本语法分析
- Elasticsearch为“非查询字段”不建索引index store
- 救护车声音
- mybatis 的逆向工程
- 开餐馆