BZOJ3626 LNOI2014LCA

Problem

BZOJ

Solution

就是给定询问l,r,z求 i = l r d e e p ( l c a ( i , z ) )
我们考虑把deep的含义转化一下,它就是表示某个点到根节点需要经过几个节点
那么把路径上的deep差分之后就变成了一条1,然后我们做一个区间询问和即可得到deep

那么我们就用这种思想,把[l,r]区间内所有点到rt的路径权值+1,再统计z到rt的权值和即为答案。可以 O ( q n log n ) 做到

但是q太大了,我们会想要优化掉它,考虑到我们可以把[l,r]转化为[1,l-1]和[1,r]的询问答案,那么我们就可以把询问拆开,然后排序,再依次把贡献算出来。即可
时间复杂度 O ( ( n + q ) log n )

Code

#include <algorithm>
#include <cstdio>
#define pushup(x) sum[x]=pls(val[x],pls(sum[ch[x][0]],sum[ch[x][1]])),sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1
#define pd(x) if(rev[x]||add[x])pushdown(x)
#define rg register
using namespace std;
typedef unsigned int ll;
const int maxn=50010,mod=201314;
struct query{
    int pos,z,pls,id;
    bool operator < (const query &x)const
    {
        if(pos==x.pos) return z<x.z;
        return pos<x.pos;
    }
}a[maxn<<1];
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
int n,m,top,p,stk[maxn],ans[maxn];
int f[maxn],ch[maxn][2],val[maxn],sz[maxn],rev[maxn],sum[maxn],add[maxn];
inline int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
void addtag(int x,int v)
{
    val[x]=pls(val[x],v);add[x]=pls(add[x],v);
    sum[x]=pls(sum[x],(ll)v*sz[x]%mod);
}
inline bool isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
void pushdown(int x)
{
    if(add[x])
    {
        if(ch[x][0]) addtag(ch[x][0],add[x]);
        if(ch[x][1]) addtag(ch[x][1],add[x]);
        add[x]=0;
    }
    if(rev[x])
    {
        rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
        rev[x]=0;swap(ch[x][0],ch[x][1]);
    }
}
void rotate(int x)
{
    int fa=f[x],ff=f[fa],l,r;
    if(ch[fa][0]==x) l=0;
    else l=1;r=l^1;
    if(!isroot(fa)) {if(ch[ff][0]==fa) ch[ff][0]=x;else ch[ff][1]=x;}
    f[x]=ff;f[fa]=x;f[ch[x][r]]=fa;
    ch[fa][l]=ch[x][r];ch[x][r]=fa;
    pushup(fa);pushup(x);
}
void splay(int x)
{
    stk[top=1]=x;
    for(int i=x;!isroot(i);i=f[i]) stk[++top]=f[i];
    for(int i=top;i;i--) pd(stk[i]);
    while(!isroot(x))
    {
        int fa=f[x],ff=f[fa];
        if(!isroot(fa))
        {
            if((ch[fa][0]==x)^(ch[ff][0]==fa)) rotate(x);
            else rotate(fa);
        }
        rotate(x);
    }
}
void access(int x){for(int t=0;x;t=x,x=f[x]) splay(x),ch[x][1]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=1;}
int find(int x){access(x);splay(x);while(ch[x][0]) x=ch[x][0];return x;}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);if(ch[y][0]==x) ch[y][0]=0,f[x]=0;}
void link(int x,int y){makeroot(x);f[x]=y;}
void input()
{
    int x,l,r;
    read(n);read(m);
    for(rg int i=1;i<=n;i++) sz[i]=1;
    for(rg int i=2;i<=n;i++){read(x);link(++x,i);}
    for(rg int i=1;i<=m;i++)
    {
        read(l);read(r);read(a[i].z);a[i].z++;l++;r++;
        a[i].pos=l-1;a[i].pls=0;
        a[i+m].pos=r;a[i+m].pls=1;a[i+m].z=a[i].z;
        a[i].id=a[i+m].id=i;
    }
    sort(a+1,a+m+m+1);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    input();
    while(a[p].pos<1) p++;
    for(rg int i=1;i<=n;i++)
    {
        split(1,i);addtag(i,1);
        while(a[p].pos<=i&&p<=m+m)
        {
            if(a[p].z!=a[p-1].z||a[p].pos!=a[p-1].pos) split(1,a[p].z);
            if(a[p].pls) ans[a[p].id]=pls(ans[a[p].id],sum[a[p].z]);
            else ans[a[p].id]=dec(ans[a[p].id],sum[a[p].z]);
            p++;
        }
    }
    for(rg int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/as_a_kid/article/details/80574310
今日推荐