zoukankan      html  css  js  c++  java
  • 2018 ICPC 焦作网络赛 E.Jiu Yuan Wants to Eat

    题意:四个操作,区间加,区间每个数乘,区间的数变成 2^64-1-x,求区间和。

    题解:2^64-1-x=(2^64-1)-x 因为模数为2^64,-x%2^64=-1*x%2^64 由负数取模的性质可知 也就 =(2^64-1)*x%2^64 所以 2^64-1-x=2^64-1+(2^64-1)*x 所以第三个操作也就变成了区间乘 和区间加。  然后就是树剖加线段树多重标记。表示这是第一次写多重标记,整体凭感觉,细节看题解,树剖有点点遗忘,不过还好。今天看群里说邀请赛没什么价值,,细想一下那些题确实裸了点,的确网络赛难啊QAQ。今天好颓,王者玩了好久。

    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define ls x<<1
    #define rs x<<1|1
    #define ull unsigned long long
    #define _mp make_pair
    #define ldb long double
    using namespace std;
    const int maxn=1e5+100;
    const ull inf=(1<<64)-1;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }struct node
    {
        int l,r;
        ull sum,add,mul;
    }no[maxn<<2];
    int siz[maxn],depth[maxn],dfn[maxn],id[maxn],son[maxn],top[maxn],fa[maxn];
    int tot;
    vector<int>g[maxn];
    int n,m;
    void dfs1(int x,int f)
    {
        depth[x]=depth[f]+1;
        fa[x]=f;
        siz[x]=1;
        for(int i=0;i<(int)g[x].size();i++)
        {
            int v=g[x][i];
            if(v==f)continue;
            dfs1(v,x);
            siz[x]+=siz[v];
            if(son[x]==-1||siz[son[x]]<siz[v])son[x]=v;
        }
    }
    void dfs2(int x,int f)
    {
        top[x]=f;
        id[x]=++tot;
        if(son[x]==-1)return;
        dfs2(son[x],f);
        for(int i=0;i<(int)g[x].size();i++)
        {
            if(g[x][i]==son[x]||g[x][i]==fa[x])continue;
            dfs2(g[x][i],g[x][i]);
        }
    }
    void push_up(int x)
    {
        no[x].sum=no[x<<1].sum+no[x<<1|1].sum;
    }
    void push_down(int x)
    {
       int len=no[x].r-no[x].l+1;
       no[x<<1].add=no[x<<1].add*no[x].mul+no[x].add;
       no[x<<1|1].add=no[x<<1|1].add*no[x].mul+no[x].add;
       no[x<<1].mul=no[x<<1].mul*no[x].mul;
       no[x<<1|1].mul=no[x<<1|1].mul*no[x].mul;
       no[x<<1].sum=no[x<<1].sum*no[x].mul+(len-(len>>1))*no[x].add;
       no[x<<1|1].sum=no[x<<1|1].sum*no[x].mul+((len>>1))*no[x].add;
       no[x].add=0;no[x].mul=1;
    }
    void build(int x,int l,int r)
    {
        no[x].l=l;no[x].r=r;
        no[x].add=0;no[x].mul=1;
        no[x].sum=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
    }
    ull query(int x,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)
        {
            return no[x].sum;
        }
        ull res=0;
        push_down(x);
        int mid=(l+r)>>1;
        if(L<=mid)res+=query(ls,l,mid,L,R);
        if(R>mid) res+=query(rs,mid+1,r,L,R);
        return res;
    }
    void update(int x,int l,int r,int L,int R,int type,ull v)
    {
        if(L<=l&&r<=R)
        {
            if(type==1)
            {
                no[x].sum=no[x].sum*v;
                no[x].add=no[x].add*v;
                no[x].mul=no[x].mul*v;
                return;
            }
            if(type==2)
            {
                no[x].sum+=v*(r-l+1);
                no[x].add+=v;
                return;
            }
            if(type==3)
            {
                no[x].sum=no[x].sum*inf+inf*(r-l+1);
                no[x].add=no[x].add*inf+inf;
                no[x].mul=no[x].mul*inf;
                return;
            }
        }
        push_down(x);
        int mid=(l+r)>>1;
        if(L<=mid)update(ls,l,mid,L,R,type,v);
        if(R>mid)update(rs,mid+1,r,L,R,type,v);
        push_up(x);
    }
    void ask1(int x,int y,int type,ull val)
    {
        int xx=top[x],yy=top[y];
        while(xx!=yy)
        {
            if(depth[xx]<depth[yy])swap(xx,yy),swap(x,y);
            update(1,1,n,id[xx],id[x],type,val);
            x=fa[xx];
            xx=top[x];
        }
        if(depth[x]<depth[y])swap(x,y);
        update(1,1,n,id[y],id[x],type,val);
    }
    ull ask2(int x,int y)
    {
        int xx=top[x],yy=top[y];
        ull aa=0;
        while(xx!=yy)
        {
            if(depth[xx]<depth[yy])swap(xx,yy),swap(x,y);
            aa+=query(1,1,n,id[xx],id[x]);
            x=fa[xx];
            xx=top[x];
        }
        if(depth[x]<depth[y])swap(x,y);
        aa+=query(1,1,n,id[y],id[x]);
        return aa;
    }
    void init()
    {
        for(int i=1;i<=n;i++)g[i].clear();
        memset(fa,0,sizeof(fa));
        memset(son,-1,sizeof(son));
        memset(depth,0,sizeof(depth));
        tot=0;
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            init();
            int tmp;
            for(int i=2;i<=n;i++)
            {
                scanf("%d",&tmp);
                g[tmp].pb(i);
            }
            dfs1(1,0);
            dfs2(1,1);
            build(1,1,n);
            scanf("%d",&m);
            int pp,qq,rr;
            ull s;
            for(int i=1;i<=m;i++)
            {
                scanf("%d",&tmp);
                if(tmp==1||tmp==2)
                {
                    scanf("%d%d%llu",&pp,&qq,&s);
                    ask1(pp,qq,tmp,s);
                }
                else if(tmp==3)
                {
                    scanf("%d%d",&pp,&qq);
                    ask1(pp,qq,tmp,0);
                }
                else
                {
                    scanf("%d%d",&pp,&qq);
                    cout<<ask2(pp,qq)<<"
    ";
                }
            }
        }
    }
    

      

  • 相关阅读:
    更换笔记本电脑记录数据迁移过程
    solaris下的目录ls不到,却能cd进去
    轻松掌握ORACLE 11GR2的RAC实施
    魏公村口腔医院挂号
    springstrutshibernate学习
    oracle RAC启动序列
    HPUX内存监控
    DOM操作 vs. innerHTML
    oracle导入导出技巧
    jQuery幻灯片带缩略图平移滑动焦点图
  • 原文地址:https://www.cnblogs.com/intwentieth/p/9726751.html
Copyright © 2011-2022 走看看