BZOJ3626 [LNOI2014]LCA
来源:互联网 发布:晨兴资本 知乎 编辑:程序博客网 时间:2024/05/22 05:26
链剖,由于询问是询问一段区间内的所以我们建主席树,造两颗主席树,一个维护点的个数,一个维护点的深度和,对于每个点x,往根走,每走一条轻边到达轻边的父亲结点f,就在主席树上给f的点个数+1,深度和+f的深度(默认刚开始是走了一条轻边到达点x的)
查询的时候每走一条轻边到达一条重链上的结点x,求出重链上x和x以下有多少个点,再减去从来那条轻边底下来的点的个数,剩下这些点和询问点的lca都是x,用点的个数*x的深度记入答案,对于重链上x以上的点,LCA就是那些点,求深度和加到答案里,然后走到重链顶端的轻边上边并更新从轻边带上来的点数(默认刚开始是走了一条轻边到达询问点)
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<iomanip>#include<ctime>#include<vector>#include<stack>#include<set>#include<bitset>#include<map>#include<queue>using namespace std;#define MAXN 50010#define MAXM 10000010#define MOD 201314#define INF 1000000000#define eps 1e-8#define ll long long struct vec{ int to; int fro;};vec mp[MAXN*2];int tai[MAXN],cnt;int siz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],dfn[MAXN],ndf[MAXN],tp[MAXN],lw[MAXN],tim;int n,m,q;int srt[MAXN],drt[MAXN];int v[MAXM],Son[MAXM][2];int tot;int now;inline void be(int x,int y){ mp[++cnt].to=y; mp[cnt].fro=tai[x]; tai[x]=cnt;}inline void bde(int x,int y){ be(x,y); be(y,x);}void dfs1(int x){ int i,y; siz[x]=1; dep[x]=dep[fa[x]]+1; for(i=tai[x];i;i=mp[i].fro){ y=mp[i].to; if(!siz[y]){ fa[y]=x; dfs1(y); siz[x]+=siz[y]; if(siz[y]>siz[son[x]]){ son[x]=y; } } }}void dfs2(int x,int z){ int i,y; tp[x]=z; lw[z]=x; dfn[x]=++tim; ndf[tim]=x; if(son[x]){ dfs2(son[x],z); for(i=tai[x];i;i=mp[i].fro){ y=mp[i].to; if(!dfn[y]){ dfs2(y,y); } } }}void change(int &x,int xx,int y,int z,int p,int cv){ x=++tot; v[x]=(v[xx]+cv)%MOD; memcpy(Son[x],Son[xx],sizeof(Son[x])); if(y==z){ return ; } int mid=y+z>>1; if(p<=mid){ change(Son[x][0],Son[xx][0],y,mid,p,cv); }else{ change(Son[x][1],Son[xx][1],mid+1,z,p,cv); }}void tochange(int x){ while(x){ change(srt[now],srt[now],1,n,dfn[x],1); change(drt[now],drt[now],1,n,dfn[x],dep[x]); x=fa[tp[x]]; }}int ask(int x,int xx,int y,int z,int l,int r){ if(l>r||!l){ return 0; } if(y==l&&z==r){ return (v[xx]-v[x]+MOD)%MOD; } int mid=y+z>>1; if(r<=mid){ return ask(Son[x][0],Son[xx][0],y,mid,l,r); }else if(l>mid){ return ask(Son[x][1],Son[xx][1],mid+1,z,l,r); }else{ return (ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r))%MOD; }}int toask(int l,int r,int x){ int lu=0; int re=0; while(x){ (re+=(ll)ask(srt[l-1],srt[r],1,n,dfn[son[x]],dfn[lw[tp[x]]])*dep[x]%MOD)%=MOD; (re+=(ll)(ask(srt[l-1],srt[r],1,n,dfn[x],dfn[x])-lu)*dep[x]%MOD)%=MOD; (re+=ask(drt[l-1],drt[r],1,n,dfn[tp[x]],dfn[fa[x]]))%=MOD; lu=ask(srt[l-1],srt[r],1,n,dfn[tp[x]],dfn[lw[tp[x]]]); x=fa[tp[x]]; } return re;}int main(){ int i,x,y,l,r; scanf("%d%d",&n,&m); for(i=2;i<=n;i++){ scanf("%d",&x); x++; bde(x,i); } dfs1(1); dfs2(1,1); for(now=1;now<=n;now++){ srt[now]=srt[now-1]; drt[now]=drt[now-1]; tochange(now); } while(m--){ scanf("%d%d%d",&l,&r,&x); l++; r++; x++; printf("%d\n",toask(l,r,x)); } return 0;} /*7 1000 0 1 1 2 2 */
0 0
- 【BZOJ3626】 [LNOI2014]LCA
- BZOJ3626: [LNOI2014]LCA
- bzoj3626【LNOI2014】LCA
- [BZOJ3626] [LNOI2014]LCA
- BZOJ3626: [LNOI2014]LCA
- [bzoj3626][LNOI2014]LCA
- [LNOI2014][BZOJ3626]LCA
- BZOJ3626 [LNOI2014]LCA
- bzoj3626[LNOI2014] LCA
- BZOJ3626: [LNOI2014]LCA LCT
- [BZOJ3626][LNOI2014]LCA 树链剖分
- 【LNOI2014】bzoj3626 LCA
- bzoj3626: [LNOI2014]LCA
- bzoj3626[LNOI2014]LCA 树链剖分
- bzoj3626 [LNOI2014]LCA
- [bzoj3626][LNOI2014]LCA 树链剖分
- bzoj3626: [LNOI2014]LCA
- BZOJ3626 [LNOI2014]LCA(树链剖分)
- NOIP提高组2015 飞扬的小鸟
- 圣邦微新产品发布1.5A 闪光灯驱动:SGM3785
- 剑指Offer算法题JAVA版4-12题(全是个人写的非官方,只供参考和自己复习,测试用例都通过了)
- java中Object转String
- 2016-7-2日总结
- BZOJ3626 [LNOI2014]LCA
- libuv学习笔记(22)
- 动态菜单栏
- MFC进度栏的编程(SDI)
- 静态变量
- iOS开发思想
- Android中ImageView和ImageButton的比较详解
- uva 202--Repeating Decimal
- android 16进制颜色值字符串转int值