題目要求在樹上找到一條鏈使得這條鏈上的點的乘積模mod等於k,求鏈首尾字典序最小的一條
看到題目就能知道是乙個點分治的題目,將樹按照重心分治之後,就是要統計以重心為根的子樹中,過樹根的mod為k的鏈字典序最小的一條,這裡的統計必需是在時間複雜度o(n) 以下才能過
**:
#pragma comment(linker,"/stack:102400000,102400000")
#include
using
namespace
std;
const
int maxn = 100000 + 50,mod = 1000000 + 3,inf = 0x3f3f3f3f;
typedef
long
long ll;
struct edgeedges[maxn * 2];
int head[maxn],tot;
void edge_init()
void insert_edge(int u,int v)
int n;
ll k;
ll node_value[maxn];
ll inv[mod];
int _hash[mod],flag[mod];
void init_inv()
int size[maxn],center,center_size;
int vis[maxn];
void getinfo(int rt,int fa)
}void getcenter(int rt,int fa,const
int tot_size)
if(tmp_size < center_size) center = rt,center_size = tmp_size;
}int ans_a,ans_b;
void update_ans(int a,int b)
ll path_value[maxn];
int path_value_node[maxn],path_cnt;
void solve_dfs(int rt,int fa,ll pre_value)
}int lable;
void solve(int rt)
for(int j = 0;j < path_cnt;++j)
}lable++;
for(i = head[rt];~i;i = edges[i].pre)
}int main()
memset(vis,0,sizeof vis);
memset(flag,0,sizeof flag);
ans_a = ans_b = inf;lable = 1;
solve(1);
if(ans_a != inf) printf("%d %d\n",ans_a,ans_b);
else
printf("no solution\n");
}return
0;}
樹的點分治 HDU4812 D Tree
題目傳送門 這次英語題應該比較好懂吧 大意是給定一棵有n nn個點的樹,每個點有權值v iv i vi 求是否存在一條路徑使得路徑上所有點的權值的乘積mod 106 3 bmod 10 6 3 mod106 3為k kk,輸出路徑首尾編號,若有多解輸出字典序最小的解。貌似很像不虛就是要ak?現在求路...
HDU4812 D Tree(樹的點分治)
題目大概說給一棵有點權的樹,輸出字典序最小的點對,使這兩點間路徑上點權的乘積模1000003的結果為k。樹的點分治搞了。因為是點權過根的兩條路徑的lca會被重複統計,而注意到1000003是質數,所以這個用乘法逆元搞一下就ok了。還有要注意 治 的各個實現,把時間複雜度 控制 在o nlogn wa...
hdu(1007) 最近點對 分治法
最近點對一般想到列舉 一一枚舉時間複雜度為n 2 列舉時候一些操作是多餘的,有了分治演算法的思想 把一些問題分個擊破,再回到整體。題目鏈結 以這道題為例,我們可以把他按照x軸的公升序分成多個子區域先在子區域中求最近點距離,然後將相鄰兩個子區域合併,看看兩個子區域中有沒有更小的。大致思想就是這樣的。設...