【洛谷】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 }
这个是第二种
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 }
这个是我的第一篇博客,开通博客打算记录自己的acm历程。
大学才接触编程,只是觉得acm很有趣所以才坚持下来,虽然现在还是很弱,很多东西都不会,但是打acm与我而言是兴趣,就算没有成绩也想打下去。希望以后会更好吧。