zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat (树链剖分-线性变换线段树)

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

    [-xequiv (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
    ",Qsum(u,v));
                }
            }
        }
        return 0;
    }
    
    
    为了更好的明天
  • 相关阅读:
    layui日历控件设置选择日期不能超过当前日期
    layui表格工具条,如何动态控制按钮的展示?
    celery定时任务
    redis的安装(windows+linux)
    redis常用操作
    mac通过virtualbox安装win10
    制作U盘启动盘
    k8s报错: * spec.template.spec.volumes[0].name: Invalid value: "nfs_pvc001": must match the regex [a-z0-9]([-a-z0-9]*[a-z0-9])? (e.g. 'my-name' or '123-abc')
    k8s的容器的端口暴露
    k8s中pod文件的定义格式
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9651737.html
Copyright © 2011-2022 走看看