码迷,mamicode.com
首页 > 其他好文 > 详细

ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat (树链剖分-线性变换线段树)

时间:2018-09-15 18:46:50      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:spl   比较   不能   next   swap   \n   splay   struct   wan   

树链剖分若不会的话可自行学习一下.
前两种操作是线性变换,模\(2^{64}\)可将线段树全部用unsigned long long 保存,另其自然溢出.
而取反操作比较不能直接处理,因为其模\(2^{64}\)的特殊性,可将其转化为线性变换.
显然
\[-x\equiv (2^{64}-1)*x (mod\ 2^{64})\]
因为\[!x = (2^{64}-1) -x \]
所以
\[ !x = (2^{64}-1) + (2^{64}-1)x\]

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
typedef unsigned long long LL;
LL TTT = 0xffffffffffffffff;
using namespace std;
const int maxn =1e5+5;
struct Edge{
    int to,next;
}E[2*maxn];
int n,head[maxn],tot;
int cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];

void init()
{
    cnt=idx=tot=0;
    memset(head,-1,sizeof(head));
    dep[1]=0,fa[1]=1,size[0]=0;
    memset(son,0,sizeof(son));
}

void AddEdge(int u,int v)
{
    E[tot] = (Edge){v,head[u]};
    head[u]=tot++;
}
void dfs1(int u)
{
    size[u]=1;
    for(int i=head[u];~i;i=E[i].next){
        int v=E[i].to;
        if(v!=fa[u]){
            fa[v]=u;
            dep[v]=dep[u]+1;
            dfs1(v);
            size[u]+=size[v];
            if(size[son[u]]<size[v]) son[u]=v;
        }
    }
}

void dfs2(int u,int topu)
{
    top[u]= topu;
    id[u] = ++idx;
    rnk[idx] = u;
    if(!son[u]) return;
    dfs2(son[u],top[u]);
    for(int i=head[u];~i;i=E[i].next){
        int v=E[i].to;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    }
}

struct Node{
    LL sum,add,b;
    bool nt;
}tree[maxn<<2];
void pushup(int rt){
    tree[rt].sum = tree[lson].sum + tree[rson].sum;
}

void pushdown(int l,int r,int rt)
{
    int m = (l+r)>>1;
    if(tree[rt].add!=1){
        tree[lson].sum *= tree[rt].add;
        tree[rson].sum *= tree[rt].add;
        tree[lson].b *= tree[rt].add;
        tree[rson].b *= tree[rt].add;
        tree[lson].add *= tree[rt].add;
        tree[rson].add *= tree[rt].add;
        tree[rt].add = 1;
    }
    if(tree[rt].b){
        tree[lson].sum += (m-l+1)* tree[rt].b;
        tree[rson].sum += (r-m) *tree[rt].b;
        tree[lson].b += tree[rt].b;
        tree[rson].b += tree[rt].b;
        tree[rt].b= 0;
    }
}

void build(int l,int r,int rt)
{
    tree[rt].add =1;
    tree[rt].b =0;
    tree[rt].nt = 0;
    if(l==r){
        tree[rt].sum = 0;
        return;
    }
    int m = (l+r)>>1;
    build(Lson);
    build(Rson);
    pushup(rt);
}

void update(int L,int R,LL k,LL b,int l=1,int r=n,int rt=1)
{
    if(L<=l && R>=r){
        tree[rt].sum *= k;
        tree[rt].add *= k;
        tree[rt].b *= k;
        tree[rt].sum += (r-l+1)*b;
        tree[rt].b +=b;
        tree[rt].nt = 0;
        return;
    }
    pushdown(l,r,rt);
    int m = (l+r)>>1;
    if(L<=m) update(L,R,k,b,Lson);
    if(R>m) update(L,R,k,b,Rson);
    pushup(rt);
}

LL query(int L,int R,int l=1,int r= n,int rt=1)
{
    if(L<=l && R>=r){
        return tree[rt].sum;
    }
    pushdown(l,r,rt);
    LL ans=0;
    int m = (l+r)>>1;
    if(L<=m) ans += query(L,R,Lson);
    if(R>m) ans += query(L,R,Rson);
    return ans;
}

void change(int u,int v,int op,LL val)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        if(op==1){
            update(id[top[u]],id[u],(LL)1,val);
        }
        else if(op==2){
            update(id[top[u]],id[u],val,0);
        }
        else{
            update(id[top[u]],id[u],TTT,TTT);
        }
        u = fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    if(op==1){
        update(id[u],id[v],(LL)1,val);
    }
    else if(op==2){
        update(id[u],id[v],val,0);
    }
    else{
        update(id[u],id[v],TTT,TTT);
    }
    return ;
}

LL Qsum(int u,int v)
{
    LL ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans += query(id[top[u]],id[u]);
        u = fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    ans += query(id[u],id[v]);
    return ans;
}


int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int u,v,Q;
    while(scanf("%d",&n)==1){
        init();
        for(int i=2;i<=n;++i){
            scanf("%d",&u);
            AddEdge(u,i);
            AddEdge(i,u);
        }
        dfs1(1);
        dfs2(1,1);
        build(1,n,1);
        scanf("%d",&Q);
        int op;
        LL tmp;
        while(Q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d %d %lld",&u, &v, &tmp);
                change(u,v,2,tmp);
            }
            else if(op==2){
                scanf("%d %d %llu",&u, &v,&tmp);
                change(u,v,1,tmp);
            }
            else if(op==3){
                scanf("%d %d",&u, &v);
                change(u,v,3,0);
            }
            else{
                scanf("%d %d",&u, &v);
                printf("%llu\n",Qsum(u,v));
            }
        }
    }
    return 0;
}

ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat (树链剖分-线性变换线段树)

标签:spl   比较   不能   next   swap   \n   splay   struct   wan   

原文地址:https://www.cnblogs.com/xiuwenli/p/9651737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!