hdoj4812 D Tree(点分治)
题目链接:https://vjudge.net/problem/HDU-4812
题意:给定一颗带点权的树,求是否存在一条路经的上点的权值积取模后等于k,如果存在多组点对,输出字典序最小的。
思路:
点分治模板题。按照套路,找重心,求出子树中节点到重心的权值积取模后的值dis[i](包括重心的权值,也不可以不包括,一样的),用id[j]记录该路径的端点,用的是点分治的第二种写法。递归时,用桶mine[i]记录到重心权值积为i的最小编号。然后查找时,对dis[j],满足要求的tmp为:tmp*dis[j]%MOD=k*V[u],因为我们的dis中包括重心的权值,所以重心的权值被乘了2次。然后用到了逆元,tmp=k*V[u]%MOD*inv[dis[j]]%MOD。更新完答案后就更新桶。
因为没看清题目,题目求得点对(a,b)是a<b,而我以为(a,a)也满足,然后就找了两小时bug,崩溃到想锤电脑QAQ...。
AC代码:
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
using namespace std; inline int read(){
int x=,f=;char ch=;
while(!isdigit(ch)) {f|=ch=='-';ch=getchar();}
while(isdigit(ch)) x=(x<<)+(x<<)+(ch^),ch=getchar();
return f?-x:x;
} typedef long long LL;
const int maxn=1e5+;
const int MOD=1e6+;
const int maxk=1e6+;
const int inf=0x3f3f3f3f;
struct node1{
int v,nex;
}edge[maxn<<]; struct node2{
int x,y;
node2(){x=y=;}
node2(int x,int y):x(x),y(y){}
}ans; bool operator < (node2 a,node2 b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
} int n,k,cnt,head[maxn],sz[maxn],mson[maxn],Min,root,size;
int vis[maxn],mine[maxk],id[maxn],t,tt;
LL V[maxn],dis[maxn],inv[maxk]; void init(){
inv[]=;
for(int i=;i<maxk;++i)
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
} void adde(int u,int v){
edge[++cnt].v=v;
edge[cnt].nex=head[u];
head[u]=cnt;
} void getroot(int u,int fa){
sz[u]=,mson[u]=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]||v==fa) continue;
getroot(v,u);
sz[u]+=sz[v];
mson[u]=max(mson[u],sz[v]);
}
mson[u]=max(mson[u],size-sz[u]);
if(mson[u]<Min) Min=mson[u],root=u;
} void getdis(int u,int fa,LL len){
dis[++t]=len,id[t]=u;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]||v==fa) continue;
getdis(v,u,len*V[v]%MOD);
}
} void solve(int u){
mine[V[u]]=u,t=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]) continue;
tt=t;
getdis(v,u,V[u]*V[v]%MOD);
for(int j=tt+;j<=t;++j){
LL tmp=1LL*k*V[u]%MOD*inv[dis[j]]%MOD;
if(mine[tmp]==inf) continue;
node2 other;
if(mine[tmp]<id[j]) other.x=mine[tmp],other.y=id[j];
else other.x=id[j],other.y=mine[tmp];
if(other<ans) ans=other;
}
for(int j=tt+;j<=t;++j)
mine[dis[j]]=min(mine[dis[j]],id[j]);
}
mine[V[u]]=inf;
for(int i=;i<=t;++i)
mine[dis[i]]=inf;
} void fenzhi(int u,int ssize){
vis[u]=;
solve(u);
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]) continue;
Min=inf,root=;
size=sz[v]<sz[u]?sz[v]:(ssize-sz[u]);
getroot(v,);
fenzhi(root,size);
}
} int main(){
init();
memset(mine,0x3f,sizeof(mine));
while(~scanf("%d%d",&n,&k)){
cnt=;
ans.x=ans.y=n+;
for(int i=;i<=n;++i)
head[i]=vis[i]=;
for(int i=;i<=n;++i){
int tmp=read();
V[i]=tmp;
}
for(int i=;i<n;++i){
int u=read(),v=read();
adde(u,v);
adde(v,u);
}
Min=inf,root=,size=n;
getroot(,);
fenzhi(root,n);
if(ans.x==n+)
printf("No solution\n");
else
printf("%d %d\n",ans.x,ans.y);
}
return ;
}
hdoj4812 D Tree(点分治)的更多相关文章
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
- HDU 4812 D Tree 树分治+逆元处理
D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing Unive ...
- POJ 1741 Tree 树分治
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...
- [bzoj 1468][poj 1741]Tree [点分治]
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- 【CF434E】Furukawa Nagisa's Tree 点分治
[CF434E]Furukawa Nagisa's Tree 题意:一棵n个点的树,点有点权.定义$G(a,b)$表示:我们将树上从a走到b经过的点都拿出来,设这些点的点权分别为$z_0,z_1... ...
- POJ 1741 Tree(点分治点对<=k)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- poj 1744 tree 树分治
Tree Time Limit: 1000MS Memory Limit: 30000K Description Give a tree with n vertices,each ed ...
- CF1039D You Are Given a Tree 根号分治,贪心
CF1039D You Are Given a Tree LG传送门 根号分治好题. 这题可以整体二分,但我太菜了,不会. 根号分治怎么考虑呢?先想想\(n^2\)暴力吧.对于每一个要求的\(k\), ...
随机推荐
- PHP mysqli_next_result() 函数
定义和用法 mysqli_next_result() 函数为 mysqli_multi_query() 准备下一个结果集. 语法 mysqli_next_result(connection); 执 ...
- 使用StringBuilder写XML遭遇UTF-16问题
http://www.cnblogs.com/jans2002/archive/2007/08/05/843843.html
- Java中二维数组
二维数组:(其实是一个一维数组,它的每一个元素又是一个一维数组), 可以看做是一张表格. 初始化: 动态初始化 int[ ][ ] arr = new int[3][2]; 定义了一个二维数组,其中 ...
- SRS之SrsHlsCache::reap_segment详解
1. 是否可切片的检测 首先在调用 SrsHlsCache::reap_segment 函数进行切片时,针对音频或视频,都会有一个函数来进行检测当前片的时长是否符合所要求的时长. 对于音频,会调用 S ...
- (转载)IOCP 浅析
转自:http://www.ibm.com/developerworks/cn/java/j-lo-iocp/#author 郭 仁祥, 软件工程师, IBM 简介: 传统的 Server/Cli ...
- axios的get请求无法设置Content-Type
最近在与后端的项目对接中,接口工具使用了axios这个东西.怎么说那 ,反正有很多坑,在后端的请求中要设置GET 请求中要设置header中的Content-Type为application/json ...
- Qt DLL总结【二】-创建及调用QT的 DLL
开发环境:VS2008+Qt4.7.4 最近看了不少Qt的DLL例子,总结一下如何创建和调用QT 动态链接库. 先讲一下对QT动态链接库的调用方法,主要包括: 1.显式链接DLL,调用DLL的全局函数 ...
- [Mybatis]执行一句Sql返回一个List<String>
在Mapper.xml如下书写SQL文,其中 resultType告知MyBatis返回的类型: <select id="selectExpiredDate" resultT ...
- VIM | vim操作大全
1. 关于Vim vim是Linux下第二强大的编辑器. 虽然emacs是公认的世界第一,我认为使用emacs并没有使用vi进行编辑来得高效. 如果是初学vi,运行一下vimtutor是个聪明的决定. ...
- opencv配置运行问题
opencv是图像处理常用的一个库文件,对于一些新手来说,配置完后运行,总会有这样或者那样的错误,会挫伤其学习积极性,这里将常见的几种错误列举出来,供其参考和使用. 方法/步骤第一种错误叫no suc ...