P3806 【模板】点分治1

本文深入探讨了一道经典的树形DP模板题,通过暴力解法引入,进而优化到使用树形DP结合二分搜索的高效算法。文章详细讲解了树重心、树形DP以及二分搜索在解决特定类型问题中的应用,为读者提供了完整的代码实现与思路解析。

一道淀粉质的模版题,开始是暴力

 1 #include <bits/stdc++.h>
 2 #define up(i,l,r) for(register int i = (l); i <= (r); ++i)
 3 #define dn(i,l,r) for(register int i = (l); i >= (r); --i)
 4 #define ll long long
 5 #define re register
 6 using namespace std;
 7 
 8 template <typename T> void in(T &x) {
 9     x = 0; T f = 1; char ch = getchar();
10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
12     x *= f;
13 }
14 
15 template <typename T> void out(T x) {
16     if(x < 0) x = -x , putchar('-');
17     if(x > 9) out(x/10);
18     putchar(x%10 + 48);
19 }
20 //---------------------------------------------------------
21 
22 const int N = 10007;
23 
24 int n,m;
25 
26 struct edge {
27     int v,w,nxt;
28 }e[N<<1]; int tot,head[N];
29 
30 void add(int u,int v,int w) {
31     e[++tot].v = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot;
32 }
33 
34 int Tsize,f[N],rt;
35 int size[N];
36 bool vis[N];
37 
38 void get_rt(int u,int fa) {
39     size[u] = 1; f[u] = 0;
40     for(re int i = head[u];i ;i = e[i].nxt) {
41         int v = e[i].v; if(v == fa || vis[v]) continue;
42         get_rt(v,u);
43         size[u] += size[v]; f[u] = max(f[u],size[v]); 
44     }
45     f[u] = max(f[u],Tsize - size[u]);
46     if(f[u] < f[rt]) rt = u;
47 }
48 
49 int dis[N],cdis[N];
50 int ans[102210101];
51 int cnt;
52 
53 void get_dis(int u,int fa) {
54     cdis[++cnt] = dis[u];
55     for(re int i = head[u]; i; i = e[i].nxt) {
56         int v = e[i].v; if(v == fa || vis[v]) continue;
57         dis[v] = dis[u] + e[i].w; get_dis(v,u);
58     }
59 }
60 
61 void calc(int u,int w) {
62     cnt = 0; get_dis(u,0);
63     up(i,1,cnt) {
64         up(j,1,cnt) {
65             if(i != j)
66             ans[cdis[i] + cdis[j]] += w;
67         }
68     }
69 }
70 
71 void solve(int u) {
72     vis[u] = 1; dis[u] = 0; calc(u,1);
73     for(re int i = head[u]; i; i = e[i].nxt) {
74         int v = e[i].v; if(vis[v]) continue;
75         dis[v] = e[i].w; calc(v,-1);
76         Tsize = size[v]; rt = 0;
77         get_rt(v,0); solve(rt);
78     }
79 }
80 
81 int main() {
82     in(n); in(m); int x,y,w;
83     up(i,1,n-1) {
84         in(x); in(y); in(w);
85         add(x,y,w); add(y,x,w);
86     }
87     Tsize = n,f[0] = n+1,rt = 0;
88     get_rt(1,0); solve(rt);
89     int k;
90     up(i,1,m) {
91         in(k);
92         if(ans[k]) printf("AYE\n");
93         else printf("NAY\n");
94     }
95     return 0;
96 }

然后我用了二分

  1 #include <bits/stdc++.h>
  2 #define up(i,l,r) for(register int i = (l); i <= (r); ++i)
  3 #define dn(i,l,r) for(register int i = (l); i >= (r); --i)
  4 #define ll long long
  5 #define re register
  6 using namespace std;
  7 
  8 template <typename T> void in(T &x) {
  9     x = 0; T f = 1; char ch = getchar();
 10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
 11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
 12     x *= f;
 13 }
 14 
 15 template <typename T> void out(T x) {
 16     if(x < 0) x = -x , putchar('-');
 17     if(x > 9) out(x/10);
 18     putchar(x%10 + 48);
 19 }
 20 //---------------------------------------------------------
 21 
 22 const int N = 10007;
 23 
 24 int n,m;
 25 
 26 struct edge {
 27     int v,w,nxt;
 28 }e[N<<1]; int tot,head[N];
 29 
 30 void add(int u,int v,int w) {
 31     e[++tot].v = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot;
 32 }
 33 
 34 int Tsize,f[N],rt;
 35 int size[N];
 36 bool vis[N];
 37 
 38 void get_rt(int u,int fa) {
 39     size[u] = 1; f[u] = 0;
 40     for(re int i = head[u];i ;i = e[i].nxt) {
 41         int v = e[i].v; if(v == fa || vis[v]) continue;
 42         get_rt(v,u);
 43         size[u] += size[v]; f[u] = max(f[u],size[v]);
 44     }
 45     f[u] = max(f[u],Tsize - size[u]);
 46     if(f[u] < f[rt]) rt = u;
 47 }
 48 
 49 int dis[N];
 50 int cnt;
 51 int belong;
 52 
 53 struct cur {
 54     int dis,bl;
 55     bool operator < (const cur &x) const {
 56         return dis < x.dis;
 57     }
 58 }c[N];
 59 
 60 void get_dis(int u,int fa) {
 61     c[++cnt] = (cur){dis[u],belong};
 62     for(re int i = head[u]; i; i = e[i].nxt) {
 63         int v = e[i].v; if(v == fa || vis[v]) continue;
 64         dis[v] = dis[u] + e[i].w; get_dis(v,u);
 65     }
 66 }
 67 
 68 int binary(int x) {
 69     int l = 1,r = cnt; int res = 0;
 70     while(l <= r) {
 71         int mid = (l+r)>>1;
 72         if(x <= c[mid].dis) res = mid,r = mid - 1;
 73         else l = mid + 1;
 74     }
 75     return res;
 76 }
 77 
 78 bool test[107];
 79 int flag;
 80 int k[107];
 81 
 82 void calc(int u) {
 83     cnt = 0;
 84     
 85     for(re int i = head[u];i;i = e[i].nxt) {
 86         int v = e[i].v; if(vis[v]) continue;
 87         dis[v] = e[i].w; belong = v; get_dis(v,u);
 88     }
 89     
 90     c[++cnt] = (cur){0,0};//自己也算一个; 
 91     
 92     sort(c+1,c+cnt+1);
 93     
 94     up(i,1,m) {
 95         up(j,1,cnt) {
 96             if(flag == 0) return;
 97             if(test[i]) break;
 98             int r = binary(k[i]-c[j].dis);
 99             if(c[j].bl != c[r].bl && c[j].dis + c[r].dis == k[i]) {
100                 test[i] = 1; flag -= i; break;
101             }
102         }
103     }
104 }
105 
106 void solve(int u) {
107     if(flag == 0) return;
108     vis[u] = 1; dis[u] = 0; 
109     calc(u);
110     for(re int i = head[u]; i; i = e[i].nxt) {
111         int v = e[i].v; if(vis[v]) continue;
112         Tsize = size[v]; rt = 0;
113         get_rt(v,0); solve(rt);
114     }
115 }
116 
117 int main() {
118     in(n); in(m); int x,y,w;
119     
120     up(i,1,n-1) {
121         in(x); in(y); in(w);
122         add(x,y,w); add(y,x,w);
123     }
124     up(i,1,m) in(k[i]);
125     
126     flag = (m*(m+1))/2;
127     
128     Tsize = n,f[0] = n+1,rt = 0;
129     get_rt(1,0); solve(rt);
130     
131     up(i,1,m) {
132         if(test[i]) printf("AYE\n");
133         else printf("NAY\n");
134     }
135     
136     return 0;
137 }

虽然还可以更快,但我不想打了

转载于:https://www.cnblogs.com/mzg1805/p/10772575.html

p1177是《算法导论》(Introduction to Algorithms)这本书中的一个问题编号,它通常指的是书中关于排序算法的内容。在这本书中,排序算法是一个核心主题,其中包括许多经典算法如冒泡排序、插入排序、选择排序、希尔排序、归并排序、快速排序等。 具体到P1177,可能会涉及到某个特定排序算法的描述、分析其时间复杂度、实现细节或者是比较不同排序算法的优缺点。例如,快速排序在该页可能会有详细的递归实现讲解,而归并排序则可能涉及分治策略和合并过程。 如果你需要了解某种排序算法的具体步骤或者代码模板,比如“如何用C语言实现快速排序”,这里可以给你一个简单的快速排序的C语言模板: ```c #include <stdio.h> void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; } int partition(int arr[], int low, int high) { int pivot = arr[high]; int i = (low - 1); for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return (i + 1); } void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } // 示例 int main() { int arr[] = {10, 7, 8, 9, 1, 5}; int n = sizeof(arr) / sizeof(arr[0]); quickSort(arr, 0, n - 1); printf("Sorted array: \n"); for (int i=0; i < n; i++) printf("%d ", arr[i]); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值