【洛谷】p4178点分治模板

点分治有两种打法,一种是容斥原理,另一种是用树状数组维护

这个是第一种打法,容斥原理

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=4e4+8;
 5 int n,all,mx,root,cntd=0,cnt=0;
 6 ll ans=0,k;
 7 int h[N],siz[N];
 8 ll q[N],dis[N];
 9 bool vis[N];
10 struct edge{
11     int to,nex,w;
12 }e[N<<2];
13 void add(int u,int v,int w){
14     e[++cnt]=(edge){v,h[u],w};
15     h[u]=cnt;
16 }
17 void getrt(int u,int fa){
18     siz[u]=1;
19     int num=0;
20     for(int i=h[u];i;i=e[i].nex){
21         int v=e[i].to;
22         if(v==fa || vis[v]) continue;
23         getrt(v,u);
24         siz[u]+=siz[v];
25         num=max(num,siz[v]);
26     }
27     num=max(num,all-siz[u]);
28     if(num<mx){
29         mx=num;
30         root=u;
31     }
32 }
33 void getdis(int u,int fa){
34     q[++cntd]=dis[u];
35     for(int i=h[u];i;i=e[i].nex){
36         int v=e[i].to;
37         if(v==fa || vis[v]) continue;
38         dis[v]=dis[u]+e[i].w;
39         getdis(v,u);
40     }
41 }
42 ll calc(int u,int len){
43     cntd=0;
44     dis[u]=len;
45     getdis(u,0);
46     ll sum=0;
47     int l=1,r=cntd;
48     sort(q+1,q+1+cntd);
49     while(l<r){
50         if(q[l]+q[r]<=k) sum+=r-l,++l;
51         else --r;
52     }
53     return sum;
54 }
55 void dfs(int u){
56     ans+=calc(u,0);
57     vis[u]=1;
58     for(int i=h[u];i;i=e[i].nex){
59         int v=e[i].to;
60         if(vis[v]) continue;
61         ans-=calc(v,e[i].w);
62         all=siz[v];
63         mx=0x3f3f3f3f;
64         getrt(v,0);
65         dfs(root);
66     }
67 }
68 int main(){
69     scanf("%d",&n);
70     for(int i=1;i<n;++i){
71         int a,b,c;scanf("%d%d%d",&a,&b,&c);
72         add(a,b,c);
73         add(b,a,c);
74     }
75     scanf("%lld",&k);
76     all=n;
77     mx=0x3f3f3f3f;
78     getrt(1,0);
79     dfs(root);
80     printf("%lld",ans);
81     return 0;
82 }
View Code

这个是第二种

  1 // Cease to struggle and you cease to live
  2 // p4178
  3 #include <iostream>
  4 #include <cmath>
  5 #include <cstdio>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <queue>
  9 #include <vector>
 10 #include <set>
 11 #include <map>
 12 #include <stack>
 13 using namespace std;
 14 typedef long long ll;
 15 const int N=4e4+8;
 16 const int maxn=20000+7;
 17 int n,k,cnt;
 18 ll ans;
 19 ll tr[maxn<<4];
 20 int sav[N],era[N];
 21 int h[N],siz[N],dis[N],all,root,mx;
 22 bool vis[N];
 23 struct edge{
 24     int to,nex,w;
 25 }e[N<<1];
 26 void add(int u,int v,int w){
 27     e[++cnt]=(edge){v,h[u],w};
 28     h[u]=cnt;
 29 }
 30 void addval(int x,ll v){
 31     for(;x<=k;x+=x&(-x)) tr[x]+=v;
 32 }
 33 ll sum(int x){
 34     ll res=0;
 35     for(;x>0;x-=x&(-x)) res+=tr[x];
 36     return res;
 37 }
 38 void getrt(int u,int fa){
 39     siz[u]=1;
 40     int num=0;
 41     for(int i=h[u];i;i=e[i].nex){
 42         int v=e[i].to;
 43         if(v==fa || vis[v]) continue;
 44         getrt(v,u);
 45         siz[u]+=siz[v];
 46         num=max(num,siz[v]);
 47     }
 48     num=max(num,all-siz[u]);
 49     if(num<mx){
 50         mx=num;
 51         root=u;
 52     }
 53 }
 54 void getdis(int u,int fa){
 55     if(dis[u]>k) return;
 56     sav[++sav[0]]=era[++era[0]]=dis[u];
 57     for(int i=h[u];i;i=e[i].nex){
 58         int v=e[i].to;
 59         if(vis[v] || v==fa) continue;
 60         dis[v]=dis[u]+e[i].w;
 61         getdis(v,u);
 62     }
 63 }
 64 void cal(int u){
 65     era[0]=0;
 66     for(int i=h[u];i;i=e[i].nex){
 67         int v=e[i].to;
 68         if(vis[v]) continue;
 69         sav[0]=0;
 70         dis[v]=e[i].w;
 71         getdis(v,u);
 72         ans+=sav[0];
 73         for(int j=1;j<=sav[0];++j){
 74             ans+=sum(k-sav[j]);
 75         }
 76         for(int j=1;j<=sav[0];++j){
 77             addval(sav[j],1);
 78         }
 79     }
 80     for(int i=1;i<=era[0];++i){
 81         if(era[i]>k) continue;
 82         addval(era[i],-1);
 83     }
 84 }
 85 void dfs(int u){
 86     cal(u);
 87     vis[u]=1;
 88     for(int i=h[u];i;i=e[i].nex){
 89         int v=e[i].to;
 90         if(vis[v]) continue;
 91         all=siz[v];
 92         mx=0x3f3f3f3f;
 93         getrt(v,0);
 94         dfs(root);
 95     }
 96 }
 97 int main() {
 98     scanf("%d",&n);
 99     ans=cnt=0;
100     for(int i=1;i<n;++i){
101         int a,b,c;
102         scanf("%d%d%d",&a,&b,&c);
103         add(a,b,c);add(b,a,c);
104     }
105     scanf("%d",&k);
106     all=n;
107     mx=0x3f3f3f3f;
108     getrt(1,0);
109     dfs(root);
110     printf("%lld\n",ans);
111     return 0;
112 }
View Code

这个是我的第一篇博客,开通博客打算记录自己的acm历程。

大学才接触编程,只是觉得acm很有趣所以才坚持下来,虽然现在还是很弱,很多东西都不会,但是打acm与我而言是兴趣,就算没有成绩也想打下去。希望以后会更好吧。

posted @ 2019-05-08 11:06  小布鞋  阅读(179)  评论(0编辑  收藏  举报