[分块 暴力 树] BZOJ 4381 [POI2015]Odwiedziny
来源:互联网 发布:unity3d 汽车模型 编辑:程序博客网 时间:2024/06/05 07:14
大概就是步数小的预处理前缀和
步数大的直接倍增跳
各种细节搞得欲仙欲死
#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include<cmath>using namespace std;typedef long long ll;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++;}inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=50005;const int K=21;const int M=305;struct edge{ int u,v,next;}G[N<<1];int head[N],inum;inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;}int n,B; ll ans;int val[N],bp[N];int depth[N],fat[N][K];ll S[N][M];#define V G[p].vinline void dfs(int u,int fa){ depth[u]=depth[fa]+1; fat[u][0]=fa; for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1]; int f=fa; for (int i=1;i<=B;i++) S[u][i]=S[f][i]+val[u],f=fat[f][0]; for (int p=head[u];p;p=G[p].next) if (V!=fa) dfs(V,u);}inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=K-1;~k;k--) if ((depth[u]-depth[v])>>k&1) u=fat[u][k]; if (u==v) return u; for (int k=K-1;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[u][0];}inline int Fat(int u,int s){ for (int k=K-1;~k;k--) if (s>>k&1) u=fat[u][k]; return u;}inline ll Solve(int u,int v,int cp){ int lca=LCA(u,v),len=depth[u]+depth[v]-2*depth[lca],t,l1,l2; ll ret=0; if (len<=cp) return val[u]+val[v]; if (cp>B){ ret+=val[u]; while (1){ t=Fat(u,cp); if (depth[t]>=depth[lca])ret+=val[t],u=t; elsebreak; } if (v!=lca){ ret+=val[v]; if (len%cp){v=Fat(v,len%cp);if (depth[v]>depth[lca]) ret+=val[v]; } while (1){t=Fat(v,cp);if (depth[t]>depth[lca]) ret+=val[t],v=t;else break; } return ret; }else{ if (len%cp) ret+=val[v]; return ret; } } if (u==lca) ret+=val[lca]; else{ l1=((depth[u]-depth[lca])/cp+1)*cp; t=Fat(u,l1); ret+=S[u][cp]-S[t][cp]; } if (v!=lca){ if (len%cp) ret+=val[v],v=Fat(v,len%cp); if (depth[v]<=depth[lca]) return ret; l2=((depth[v]-depth[lca]-1)/cp+1)*cp; t=Fat(v,l2); ret+=S[v][cp]-S[t][cp]; } else{ if (len%cp) ret+=val[v]; } return ret;}int main(){ int iu,iv,ic; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); B=min(n,(int)(sqrt(n)/log(n)+1)); for (int i=1;i<=n;i++) read(val[i]); for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum); dfs(1,0); for (int i=1;i<=n;i++) read(bp[i]); for (int i=1;i<n;i++) read(ic),printf("%lld\n",Solve(bp[i],bp[i+1],ic)); return 0;}
0 0
- [分块 暴力 树] BZOJ 4381 [POI2015]Odwiedziny
- bzoj 4381: [POI2015]Odwiedziny 分块+树链剖分
- bzoj 4381: [POI2015]Odwiedziny 树链剖分
- BZOJ4381: [POI2015]Odwiedziny 分块 长链剖分
- 4381: [POI2015]Odwiedziny
- BZOJ4381: [POI2015]Odwiedziny
- [bzoj4381][POI2015]Odwiedziny
- bzoj4381: [POI2015]Odwiedziny
- BZOJ4381[POI2015] Odwiedziny
- BZOJ4381 POI2015 Odwiedziny
- BZOJ 3750: [POI2015]Pieczęć 暴力
- [BZOJ4381][POI2015]Odwiedziny (树链刨分/倍增)
- 【BZOJ 2120】 数颜色 (分块,暴力)
- BZOJ 3747 POI2015 Kinoman 线段树
- BZOJ 3747: [POI2015]Kinoman 线段树
- bzoj 3747: [POI2015]Kinoman(线段树)
- 【bzoj 3747】[POI2015]Kinoman(线段树)
- bzoj 3747: [POI2015]Kinoman 线段树
- TCP标志位#转载#
- TCP标志位
- 为什么上论坛,会显示我的浏览器和系统版本呢?
- Ztxz16学图论
- Android调试笔记——FATAL EXCEPTION: main...have you declared this activity in your AndroidManifest.xml?
- [分块 暴力 树] BZOJ 4381 [POI2015]Odwiedziny
- [LeetCode] 129. Sum Root to Leaf Numbers
- [鬼畜 树链剖分 线段树] BZOJ 2814 tree
- c# 笔记整理(2016年9月4日)
- 利用Android Studio创建AIDL并使用AIDL
- 利用Matlab绘制梯度图、散度图、旋度图
- 多线程基础
- 支付业务的数据库表的设计
- CSS3 渐变效果(20160827-0027)