BZOJ 3626 [LNOI2014]LCA - 树链剖分+线段树结构+玄学离散
2017-08-14 00:28
801 查看
考察内容:树链剖分+线段树
题意:给定一棵树,对于每一个l,r,z,求Σ(l<=i<=r)depth[lca(i,z)]
规模:n,q<=50000
分析:
1.首先考虑到倍增lca,很明显时间复杂度不允许其次考虑离线Tarjan,时间复杂度可以满足,然而会MLE
2.看到所求的值存在巨大的重复之处,考虑到莫队算法,然而不会,根号复杂度不允许,所以进行玄学离散,利用一棵查询树进行查询
3.方法只剩下了lct O(nlogn)和重链剖分O(n*log^2),然而lc不会。现在思考怎样利用树链剖分完成查询任务查询任务为一个区间,可以利用差分,求sum[r]-sum[l-1]的值。可持久化线段树,一下想到主席树,然而无法完成任务,于是进行玄学离散,将每一个ans拆成两部分,即加sum[r]和减sum[l-1],拆成两个任务来查询
4.a和b的lca深度=根节点到a的路径染色,根节点到b的路径上染色数 现在进行更新,边更新边查询,标记每个点到根的路径,路径上每个点+1,然后更新完毕查询当前时间的depth[lca],然后继续标记,结束后输出ans数组即可。
题意:给定一棵树,对于每一个l,r,z,求Σ(l<=i<=r)depth[lca(i,z)]
规模:n,q<=50000
分析:
1.首先考虑到倍增lca,很明显时间复杂度不允许其次考虑离线Tarjan,时间复杂度可以满足,然而会MLE
2.看到所求的值存在巨大的重复之处,考虑到莫队算法,然而不会,根号复杂度不允许,所以进行玄学离散,利用一棵查询树进行查询
3.方法只剩下了lct O(nlogn)和重链剖分O(n*log^2),然而lc不会。现在思考怎样利用树链剖分完成查询任务查询任务为一个区间,可以利用差分,求sum[r]-sum[l-1]的值。可持久化线段树,一下想到主席树,然而无法完成任务,于是进行玄学离散,将每一个ans拆成两部分,即加sum[r]和减sum[l-1],拆成两个任务来查询
4.a和b的lca深度=根节点到a的路径染色,根节点到b的路径上染色数 现在进行更新,边更新边查询,标记每个点到根的路径,路径上每个点+1,然后更新完毕查询当前时间的depth[lca],然后继续标记,结束后输出ans数组即可。
//a和b的lca深度= //先把根节点到a的路径都染色,然后查根节点到b的路径上染色点数 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cstdlib> #define mod 201314 using namespace std; const int maxn=50005; struct seg_tree { int lt,rt,val,add; }t[maxn<<2]; struct question { int fin,point,id,d; }q[maxn<<1]; struct edge { int to,next; }e[maxn]; int cnt,qnum,n,m,cnt_clock; int head[maxn],ans[maxn]; int size[maxn],son[maxn],top[maxn],id[maxn],pere[maxn]; bool cmp(question a,question b) { return a.fin<b.fin; } void insert(int a,int b) { e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt; } void build(int ro,int l,int r) { t[ro].lt=l; t[ro].rt=r; if(l==r)return; int mid=(l+r)>>1; build(ro<<1,l,mid); build(ro<<1|1,mid+1,r); } inline int getnum(int ro) { return t[ro].rt-t[ro].lt+1; } inline void maintain(int ro) { t[ro].val=(t[ro<<1].val+t[ro<<1|1].val)%mod; } void pushdown(int ro) { if(t[ro].add&&(t[ro].lt!=t[ro].rt)) { t[ro<<1].add+=t[ro].add; t[ro<<1|1].add+=t[ro].add; t[ro<<1].add%=mod; t[ro<<1|1].add%=mod; t[ro<<1].val+=t[ro].add*getnum(ro<<1); t[ro<<1|1].val+=t[ro].add*getnum(ro<<1|1); t[ro<<1].val%=mod; t[ro<<1|1].val%=mod; t[ro].add=0; } } void add(int ro,int l,int r,int val) { if(t[ro].lt==l&&t[ro].rt==r) { t[ro].add+=val; t[ro].val+=val*getnum(ro);//线段树写挂了233 t[ro].val%=mod; return; } pushdown(ro); int mid=(t[ro].lt+t[ro].rt)>>1; if(r<=mid)add(ro<<1,l,r,val); else if(l>=mid+1)add(ro<<1|1,l,r,val); else add(ro<<1,l,mid,val),add(ro<<1|1,mid+1,r,val); maintain(ro); } int query(int ro,int l,int r) { if(t[ro].lt==l&&t[ro].rt==r)return t[ro].val; pushdown(ro); int mid=(t[ro].lt+t[ro].rt)>>1; if(r<=mid)return query(ro<<1,l,r); else if(l>=mid+1)return query(ro<<1|1,l,r); else return (query(ro<<1,l,mid)+query(ro<<1|1,mid+1,r))%mod; } void dfs_getsz(int x) { size[x]=1; for(int i=head[x];i;i=e[i].next) { dfs_getsz(e[i].to); size[x]+=size[e[i].to]; if(size[e[i].to]>size[son[x]])son[x]=e[i].to; } } void dfs_chain(int x,int tp) { top[x]=tp; id[x]=++cnt_clock; if(son[x]) dfs_chain(son[x],tp); for(int i=head[x];i;i=e[i].next) { if(e[i].to==son[x])continue; dfs_chain(e[i].to,e[i].to); } } void chain_add(int x) { int tp=top[x]; while(x) { add(1,id[tp],id[x],1); x=pere[tp];tp=top[x]; } } int chain_query(int now) { int res=0; int x=q[now].point,tp=top[x]; while(x) { res+=query(1,id[tp],id[x]); res%=mod; x=pere[tp];tp=top[x]; } return res; } void make_seg_tree() { int now=1; for(int i=0;i<=n;i++) { chain_add(i); for(;i==q[now].fin;now++) ans[q[now].id]+=chain_query(now)*q[now].d; } } int main() { scanf("%d%d",&n,&m); for(int i=2;i<=n;i++) { int a; scanf("%d",&a); pere[i]=a+1; insert(a+1,i); } dfs_getsz(1); dfs_chain(1,1); for(int i=1;i<=m;i++) { scanf("%d",&q[++qnum].fin); q[qnum].d=-1; scanf("%d",&q[++qnum].fin); q[qnum].fin++; q[qnum].d=1; int a; scanf("%d",&a); q[qnum].point=q[qnum-1].point=a+1; q[qnum].id=q[qnum-1].id=i; } sort(q+1,q+qnum+1,cmp); build(1,1,n); make_seg_tree(); for(int i=1;i<=m;i++) printf("%d\n",(ans[i]+mod)%mod); return 0; }
相关文章推荐
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
- 【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
- BZOJ[3626][LNOI2014]LCA 树链剖分+线段树
- 【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA
- [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】
- BZOJ 3626 [LNOI2014]LCA 树链剖分 离线+差分
- [BZOJ3626][LNOI2014][树链剖分][差分][离线处理]LCA
- bzoj 3626: [LNOI2014]LCA 树链剖分
- bzoj 3626: [LNOI2014]LCA 离线+树链剖分
- BZOJ3626 [LNOI2014]LCA(树链剖分)
- [bzoj3626][LNOI2014]LCA 树链剖分
- BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
- BZOJ 3626 [LNOI2014]LCA ——树链剖分
- bzoj 3626: [LNOI2014]LCA 树链剖分
- BZOJ 3626: [LNOI2014]LCA 树链剖分 询问差分
- bzoj3626: [LNOI2014]LCA 树链剖分
- AC日记——[LNOI2014]LCA bzoj 3626
- BZOJ 3626 LCA 树链剖分