【HNOI2015】开店
来源:互联网 发布:js 字符串相等 编辑:程序博客网 时间:2024/03/28 18:08
Description
给出一棵二叉树,每个点有点权,多次询问所有点权在[l,r]范围内的点到x的距离和。
强制在线。
n<=1.5*1e5,q<=2*1e5,权值<=1e9
Solution
为什么年龄可以达到10^9呢?因为有紫asdfjawkejtwlkerj
这道题可以直接把虚树用线段树建出来,然后直接在虚树上乱搞,不过我很弱显然不会这种做法。
发现这棵树是二叉树耶,于是我们可以考虑一种又好写又能跑得过空间又小的做法:点分治!
考虑把点分树建出来,那么我就是需要对于每个点分树中的子树包含x的点统计它的子树中有多少条经过它到x的路径。
更一般一点我们需要求出某一个点的子树中除了某一个儿子的子树以外的点到x的距离和。
考虑我们求的是点分树,于是我们可以知道所有点的size之和为O(n log n)
所以我们可以暴力求出每一个点根它子树中的所有点,按年龄从小到大排序,查询这个点的时候直接二分即可。
发现这棵树是二叉树,所以我们只需要暴力开空间就够了,完全不虚。
不然可能还需要写一棵线段树emmmm
Code
#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define rep(i,a) for(int i=lst[a];i;i=nxt[i])using namespace std;typedef long long ll;int read() { char ch; for(ch=getchar();ch<'0'||ch>'9';ch=getchar()); int x=ch-'0'; for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x;}void write(ll x) { if (!x) {puts("0");return;} char ch[20];int tot=0; for(;x;x/=10) ch[++tot]=x%10+'0'; fd(i,tot,1) putchar(ch[i]); puts("");}const int N=1.5*1e5+5,M=4*1e5+5;int t[M],nxt[M],lst[N],v[M],num;void add(int x,int y,int z) { t[++num]=y;v[num]=z;nxt[num]=lst[x];lst[x]=num;}int n,m,age[N],x,y,z,l,r,a,b,A;struct P{int x,z;}p[N<<5];bool cmp(P x,P y) {return age[x.x]<age[y.x];}int size[N],Sz,rt,fa[N],L[N][3],R[N][3],cnt[N],son[N][3],tot;bool bz[N];void get_size(int x,int y) { size[x]=1; rep(i,x) if (!bz[t[i]]&&t[i]!=y) get_size(t[i],x),size[x]+=size[t[i]];}void find_root(int x,int y) { bool pd=1; rep(i,x) if (!bz[t[i]]&&t[i]!=y) { find_root(t[i],x); if (size[t[i]]>Sz/2) pd=0; } if (Sz-size[x]>Sz/2) pd=0; if (pd) rt=x;}void dfs(int x,int y,int z) { p[++tot].x=x;p[tot].z=z; rep(i,x) if (!bz[t[i]]&&t[i]!=y) dfs(t[i],x,z+v[i]);}int solve(int x,int y) { get_size(x,0); Sz=size[x];find_root(x,0); int now=rt; rep(i,now) if (!bz[t[i]]) { L[now][cnt[now]]=tot+1; dfs(t[i],now,v[i]); R[now][cnt[now]++]=tot; } int ret=0;bz[now]=1;fa[now]=y; rep(i,now) if (!bz[t[i]]) son[now][ret++]=solve(t[i],now); return now;} int fir[N<<1],dfn[N<<1],dep[N],lg[N<<1],f[18][N<<1],sum[N],tmp;ll pre[N<<5];void travel(int x,int y) { fir[x]=++tmp;dfn[tmp]=x;dep[x]=dep[y]+1; rep(i,x) if (t[i]!=y) {sum[t[i]]=sum[x]+v[i];travel(t[i],x);dfn[++tmp]=x;}}int lca(int x,int y) { x=fir[x];y=fir[y]; if (x>y) swap(x,y); int z=lg[y-x+1]; if (dep[f[z][x]]<dep[f[z][y-(1<<z)+1]]) return f[z][x]; else return f[z][y-(1<<z)+1];}int dist(int x,int y) { int z=lca(x,y); return sum[x]+sum[y]-2*sum[z];}int find(int l,int r,int v) { r++; while (l<r) { int mid=l+r>>1; if (age[p[mid].x]<=v) l=mid+1; else r=mid; } return l-1;}ll query(int x,int v) { ll res=0; for(int la=0,i=x;i;la=i,i=fa[i]) { int D=dist(x,i); res+=(age[i]<=v)*D; fo(j,0,cnt[i]-1) if (son[i][j]!=la) { int pos=find(L[i][j],R[i][j],v); res+=(ll)(pos-L[i][j]+1)*D; res+=pre[pos]-pre[L[i][j]-1]; } } return res;}int main() { freopen("shop.in","r",stdin); freopen("shop.out","w",stdout); n=read();m=read();A=read(); fo(i,1,n) age[i]=read(); fo(i,1,n-1) { x=read();y=read();z=read(); add(x,y,z);add(y,x,z); } solve(1,0); fo(i,1,n) fo(j,0,cnt[i]-1) sort(p+L[i][j],p+R[i][j]+1,cmp); fo(i,1,tot) pre[i]=pre[i-1]+p[i].z; travel(1,0); fo(i,1,tmp) f[0][i]=dfn[i],lg[i]=log(i)/log(2); fo(j,1,17) fo(i,1,tmp-(1<<j)) if (dep[f[j-1][i]]<dep[f[j-1][i+(1<<j-1)]]) f[j][i]=f[j-1][i]; else f[j][i]=f[j-1][i+(1<<j-1)]; ll ans=0; for(;m;m--) { x=read();a=read();b=read(); l=min((a+ans)%A,(b+ans)%A); r=max((a+ans)%A,(b+ans)%A); write(ans=query(x,r)-query(x,l-1)); } return 0;}
阅读全文
0 0
- 【HNOI2015】开店
- HNOI2015 开店
- HNOI2015开店
- 【HNOI2015】开店
- bzoj4012: [HNOI2015]开店
- bzoj4012: [HNOI2015]开店
- BZOJ 4012: [HNOI2015]开店
- 【HNOI2015】开店(shop)
- [HNOI2015][JZOJ4068]开店
- BZOJ4012: [HNOI2015]开店
- 4012: [HNOI2015]开店
- BZOJ 4012 [HNOI2015]开店
- bzoj 4012 [HNOI2015]开店 【树链剖分】
- 【动态树分治】【bzoj 4012】: [HNOI2015]开店
- [动态树分治] BZOJ4012 [HNOI2015]开店
- BZOJ 4012: [HNOI2015]开店 -- 动态树分治
- [BZOJ4012][HNOI2015]开店-树链剖分-主席树
- BZOJ 4012 HNOI2015 开店 动态树分治+二分
- 一切从零开始
- JS访问动态变化的对象
- 简明挂载操作教程
- Spring配置遇到的小问题
- 访问控制
- 【HNOI2015】开店
- 流程控制
- 什么是分布式系统(通俗易懂的说法)
- NodeJS教程--基于ExpressJS框架的文件上传
- 运行时动态库:not found 及介绍-Wl,-rpath
- 关于easyui在使用tab组件创建选项卡时href方式载入页面遇到的问题
- 面向对象编程的概念
- 排序算法简介
- win10+cuda8+cudnn5.1+Anaconda3+pytorch+torchvision