BZOJ 3626 [LNOI2014]LCA

来源:互联网 发布:linux网络重启 编辑:程序博客网 时间:2024/04/29 08:20

给出一个n个节点的有根树。有q次询问,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)。
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。
树链剖分+BIT
PS:用BIT求区间和非常赞

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=50005;void rd(int &r){    r=0;char c;    while(c=getchar(),c<48);    do r=r*10+(c^48);    while(c=getchar(),c>47);}int n,Q;int last[maxn],ecnt;struct Edge{    int to,nxt;}edge[maxn<<1];void ins(int u,int v){    edge[++ecnt]=(Edge){v,last[u]};    last[u]=ecnt;}int frm[maxn];int head[maxn],qcnt;struct Query{    int id,w,nxt;}qury[maxn<<1];void ins_(int id,int w,int to){    qury[++qcnt]=(Query){id,w,head[to]};    head[to]=qcnt;}int dfs_clock;int segID[maxn];int sz[maxn];int link[maxn],par[maxn];void dfs(int x){    sz[x]=1;    for(int i=last[x];i;i=edge[i].nxt){        int to=edge[i].to;        par[to]=x;        dfs(to);        sz[x]+=sz[to];    }}void assign(int x,int f){    segID[x]=++dfs_clock;    link[x]=f;    int mx=0;    for(int i=last[x];i;i=edge[i].nxt){        int to=edge[i].to;        if(sz[to]>sz[mx])            mx=to;    }    if(!mx)return;    assign(mx,f);    for(int i=last[x];i;i=edge[i].nxt){        int to=edge[i].to;        if(mx!=to)            assign(to,to);    }}struct SUM{    struct BIT{        int v[maxn];        void update(int x,int f){            for(;x<=n;x+=x&-x)v[x]+=f;        }        int query(int x){            int res=0;            for(;x;x-=x&-x)res+=v[x];            return res;        }    }bit[2];    void update(int l,int r,int x){        bit[0].update(l,(1-l)*x);        bit[0].update(r+1,r*x);        bit[1].update(l,x);        bit[1].update(r+1,-x);    }    int query(int l,int r){        int rsum=bit[1].query(r)*r+bit[0].query(r);        int lsum=bit[1].query(l-1)*(l-1)+bit[0].query(l-1);        return rsum-lsum;    }}sum;void update(int x){    while(link[x]!=0){        sum.update(segID[link[x]],segID[x],1);        x=par[link[x]];    }}int Ans[maxn];void query(int y){    int id=qury[y].id;    int x=frm[id];    int w=qury[y].w;    while(link[x]!=0){        Ans[id]+=w*sum.query(segID[link[x]],segID[x]);        x=par[link[x]];    }}void solve(){    dfs(1);    assign(1,1);    for(int i=1;i<=n;i++){        update(i);        for(int j=head[i];j;j=qury[j].nxt)            query(j);    }}void input(){    rd(n);rd(Q);    for(int u,i=2;i<=n;i++){        rd(u);++u;        ins(u,i);    }    for(int l,r,i=1;i<=Q;i++){        rd(l);rd(r);rd(frm[i]);        ++l;++r;++frm[i];        ins_(i,1,r);        if(l!=1)ins_(i,-1,l-1);    }}const int mod=201314;void output(){    for(int i=1;i<=Q;i++)        printf("%d\n",Ans[i]%mod);}int main(){    input();    solve();    output();    return 0;}
0 0
原创粉丝点击