1. 程式人生 > >P4211 [LNOI2014]LCA

P4211 [LNOI2014]LCA

又一鬼題
對於每次查詢
把l-r到跟的路上+1
然後深度就是這個位置的全職
然後查分一下,查詢r-l
這樣就可以離線記下查詢位置
只新增,不用刪除
就可以利用之前的資訊了

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define mid (l+r>>1)
using namespace std;
const int M=2e6+5,p=201314;
int n,m,head[M],tot,cnt,nex[M*2
],to[M*2],id[M],size[M],top[M],son[M],f[M],c[M],ans[M],root=1; vector<int> L[M],R[M]; struct SEG{ int sum[M],add[M];SEG(){memset(sum,0,sizeof sum);memset(add,0,sizeof add);} void update(int o){sum[o]=(sum[o<<1]+sum[o<<1|1])%p;} void pushdown(int o,int l,int r){ if
(add[o]){ add[o<<1]=(add[o]+add[o<<1])%p;add[o<<1|1]=(add[o<<1|1]+add[o])%p; sum[o<<1]=(sum[o<<1]+add[o]*(mid-l+1)%p)%p;sum[o<<1|1]=(sum[o<<1|1]+add[o]*(r-mid)%p)%p; add[o]=0; } } void modify(int o,int
l,int r,int ql,int qr){ if(l>qr||r<ql) return ; if(ql<=l&&r<=qr) {sum[o]=(sum[o]+r-l+1)%p,add[o]=(add[o]+1)%p;return;} pushdown(o,l,r); modify(o<<1,l,mid,ql,qr); modify(o<<1|1,mid+1,r,ql,qr); update(o); } int query(int o,int l,int r,int ql,int qr){ if(l>qr||r<ql) return 0; if(ql<=l&&r<=qr) {return sum[o];} pushdown(o,l,r); return query(o<<1,l,mid,ql,qr)+query(o<<1|1,mid+1,r,ql,qr); } }T; void add(int u,int v){ to[++tot]=v; nex[tot]=head[u]; head[u]=tot; } void dfs(int x){ size[x]=1; for(int i=head[x],tmp;i;i=nex[i]){ dfs(tmp=to[i]);size[x]+=size[tmp]; son[x]=(size[tmp]>size[son[x]])?tmp:son[x]; } } void dfs2(int x,int ff){ id[x]=++cnt;top[x]=ff; if(!son[x]) return ; dfs2(son[x],ff); for(int i=head[x],tmp;i;i=nex[i]) if(!id[to[i]])dfs2(to[i],to[i]); } void modify(int x){ while(x){ T.modify(1,1,cnt,id[top[x]],id[x]); x=f[top[x]]; } } int query(int x){int ans=0; while(x){ ans=(ans+T.query(1,1,cnt,id[top[x]],id[x]))%p; x=f[top[x]]; }return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=2,v;i<=n;i++){ scanf("%d",&v);v++; add(f[i]=v,i); } dfs(root);dfs2(root,root); for(int i=1,l,r;i<=m;i++) { scanf("%d%d%d",&l,&r,&c[i]);r++;c[i]++; L[l].push_back(i); R[r].push_back(i); } for(int i=1;i<=n;i++){ modify(i); for(int j=0;j<L[i].size();j++) ans[L[i][j]]=(ans[L[i][j]]-query(c[L[i][j]]))%p; for(int j=0;j<R[i].size();j++) ans[R[i][j]]=(ans[R[i][j]]+query(c[R[i][j]]))%p; } for(int i=1;i<=m;i++) printf("%d\n",(ans[i]%p+p)%p); }