AC日记——[LNOI2014]LCA bzoj 3626

3626

 

思路:

  离线操作+树剖;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
#define maxm maxn<<2
#define ll long long
#define mod 201314
struct QueryType {
    int now,id,pos,z;
    bool operator<(const QueryType pos)const
    {
        return now<pos.now;
    }
};
struct QueryType qu[maxn<<1];
int n,m,f[maxn],top[maxn],lar[maxn],size[maxn],id[maxn],deep[maxn];
int L[maxm],R[maxm],mid[maxm],head[maxn],E[maxn],V[maxn],cnt;
ll dis[maxm],ans[maxn],flag[maxm],Qes;
inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0')Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}
void dfs1(int now)
{
    size[now]=1,deep[now]=deep[f[now]]+1;
    for(int i=head[now];i;i=E[i])
    {
        dfs1(V[i]),size[now]+=size[V[i]];
        if(size[lar[now]]<size[V[i]]) lar[now]=V[i];
    }
}
void dfs2(int now,int chain)
{
    top[now]=chain,id[now]=++cnt;
    if(lar[now]) dfs2(lar[now],chain);
    for(int i=head[now];i;i=E[i])
    {
        if(V[i]==lar[now]) continue;
        dfs2(V[i],V[i]);
    }
}
void build(int now,int l,int r)
{
    L[now]=l,R[now]=r;if(l==r) return;mid[now]=l+r>>1;
    build(now<<1,l,mid[now]),build(now<<1|1,mid[now]+1,r);
}
void downdata(int now)
{
    flag[now<<1]+=flag[now],flag[now<<1|1]+=flag[now];
    dis[now<<1]+=flag[now]*(R[now<<1]-L[now<<1]+1);
    dis[now<<1|1]+=flag[now]*(R[now<<1|1]-L[now<<1|1]+1);
    flag[now]=0;
}
void add(int now,int l,int r)
{
    if(L[now]>=l&&R[now]<=r)
    {
        dis[now]+=R[now]-L[now]+1,flag[now]+=1;
        return;
    }
    if(flag[now]) downdata(now);
    if(l<=mid[now]) add(now<<1,l,r);
    if(r>mid[now]) add(now<<1|1,l,r);
    dis[now]=dis[now<<1]+dis[now<<1|1];
}
void query(int now,int l,int r)
{
    if(L[now]>=l&&R[now]<=r)
    {
        Qes+=dis[now];return;
    }
    if(flag[now]) downdata(now);
    if(l<=mid[now]) query(now<<1,l,r);
    if(r>mid[now]) query(now<<1|1,l,r);
}
void add(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) add(1,id[top[y]],id[y]),y=f[top[y]];
        else add(1,id[top[x]],id[x]),x=f[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);add(1,id[x],id[y]);
}
ll query(int x,int y)
{
    ll res=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])
        {
            Qes=0,query(1,id[top[y]],id[y]);
            res+=Qes,y=f[top[y]];
        }
        else
        {
            Qes=0,query(1,id[top[x]],id[x]);
            res+=Qes,x=f[top[x]];
        }
    }
    if(deep[x]>deep[y]) swap(x,y);
    Qes=0,query(1,id[x],id[y]);
    return res+Qes;
}
int main()
{
    freopen("data.txt","r",stdin);
    in(n),in(m);int u,v,w;
    for(int i=2;i<=n;i++)
    {
        in(u),u++,f[i]=u;
        E[++cnt]=head[u],V[cnt]=i,head[u]=cnt;
    }
    cnt=0,dfs1(1),dfs2(1,1),build(1,1,n),cnt=0;
    for(int i=1;i<=m;i++)
    {
        in(u),in(v),in(w),w++;
        qu[++cnt].now=u,qu[cnt].id=i,qu[cnt].pos=-1,qu[cnt].z=w;
        qu[++cnt].now=v,qu[cnt].id=i,qu[cnt].pos=1,qu[cnt].now++,qu[cnt].z=w;
    }
    sort(qu+1,qu+cnt+1);int tot=0;
    for(int i=1;i<=cnt;i++)
    {
        if(qu[i].now==0) continue;
        while(tot<qu[i].now) add(++tot,1);
        ans[qu[i].id]+=query(qu[i].z,1)*qu[i].pos;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]%mod);
    return 0;
}

 

posted @ 2017-06-18 18:29  IIIIIIIIIU  阅读(221)  评论(0编辑  收藏  举报