zoukankan      html  css  js  c++  java
  • 【2018焦作网络赛】 Jiu Yuan Wants to Eat (熟练剖分 + 思维)

    You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she will be queen of Tusikur, so she wanted to travel the world while she was still young. In a country, she found a small pub called Whitehouse. Just as she was about to go in for a drink, the boss Carola appeared. And ask her to solve this problem or she will not be allowed to enter the pub. The problem description is as follows:

    There is a tree with nn nodes, each node ii contains weight a[i]a[i], the initial value of a[i]a[i] is 00. The root number of the tree is 11. Now you need to do the following operations:

    1)1) Multiply all weight on the path from uu to vv by xx

    2)2) For all weight on the path from uu to vv, increasing xx to them

    3)3) For all weight on the path from uu to vv, change them to the bitwise NOT of them

    4)4) Ask the sum of the weight on the path from uu to vv

    The answer modulo 2^{64}264.

    Jiu Yuan is a clever girl, but she was not good at algorithm, so she hopes that you can help her solve this problem. Dingacksimacksimacksim

    The bitwise NOT is a unary operation that performs logical negation on each bit, forming the ones' complement of the given binary value. Bits that are 00 become 11, and those that are 11 become 00. For example:

    NOT 0111 (decimal 7) = 1000 (decimal 8)

    NOT 10101011 = 01010100

    Input

    The input contains multiple groups of data.

    For each group of data, the first line contains a number of nn, and the number of nodes.

    The second line contains (n - 1)(n1) integers b_ibi, which means that the father node of node (i +1)(i+1) is b_ibi.

    The third line contains one integer mm, which means the number of operations,

    The next mm lines contain the following four operations:

    At first, we input one integer opt

    1)1) If opt is 11, then input 33 integers, u, v, xu,v,x, which means multiply all weight on the path from uu to vv by xx

    2)2) If opt is 22, then input 33 integers, u, v, xu,v,x, which means for all weight on the path from uu to vv, increasing xx to them

    3)3) If opt is 33, then input 22 integers, u, vu,v, which means for all weight on the path from uu to vv, change them to the bitwise NOT of them

    4)4) If opt is 44, then input 22 integers, u, vu,v, and ask the sum of the weights on the path from uu to vv

    1 le n,m,u,v le 10^51n,m,u,v105

    1 le x < 2^{64}1x<264

    Output

    For each operation 44, output the answer.

    样例输入

    7
    1 1 1 2 2 4
    5
    2 5 6 1
    1 1 6 2
    4 5 6
    3 5 2
    4 2 2
    2
    1
    4
    3 1 2
    4 1 2
    3 1 1
    4 1 1

    样例输出

    5
    18446744073709551613
    18446744073709551614
    0


    SOLUTION:

    关键是处理操作3和模数的问题
    操作三其实就是(264 - 1) - x
    也就是x乘-1 ,在加264
    对于模数,unsigned溢出其实就是自动取模了

    CODE:
    #include <bits/stdc++.h>
    using namespace std;
    #define ll unsigned long long
    const ll mod=18446744073709551615;
     
    struct node1
    {
        int v;
        int next;
    };
     
    struct node2
    {
        int l;
        int r;
        ll val;
        ll laz1;
        ll laz2;
    };
     
    node1 edge[200010];
    node2 tree[400010];
    int first[100010],fa[100010],deep[100010],sum[100010],son[100010],top[100010],mp1[100010],mp2[100010];
    int n,q,num;
     
    void addedge(int u,int v)
    {
        edge[num].v=v;
        edge[num].next=first[u];
        first[u]=num++;
        return;
    }
     
    void dfsI(int cur)
    {
        int i,v;
        sum[cur]=1,son[cur]=-1;
        for(i=first[cur];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(v!=fa[cur])
            {
                fa[v]=cur,deep[v]=deep[cur]+1;
                dfsI(v);
                sum[cur]+=sum[v];
                if(son[cur]==-1||sum[son[cur]]<sum[v]) son[cur]=v;
            }
        }
        return;
    }
     
    void dfsII(int cur,int tp)
    {
        int i,v;
        num++;
        top[cur]=tp,mp1[cur]=num,mp2[num]=cur;
        if(son[cur]==-1) return;
        dfsII(son[cur],tp);
        for(i=first[cur];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(v!=fa[cur]&&v!=son[cur]) dfsII(v,v);
        }
        return;
    }
     
    void changeI(int cur,ll val)
    {
    	ll len;
    	len=tree[cur].r-tree[cur].l+1;
    	tree[cur].val=tree[cur].val+val*len;
    	return;
    }
     
    void changeII(int cur,ll val)
    {
    	tree[cur].val=tree[cur].val*val;
    	return;
    }
     
    void pushup(int cur)
    {
    	tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
    	return;
    }
     
    void pushdown(int cur)
    {
        if(tree[cur].laz1!=0||tree[cur].laz2!=1)
        {
            changeII(2*cur,tree[cur].laz2);
            changeI(2*cur,tree[cur].laz1);
            tree[2*cur].laz2=tree[2*cur].laz2*tree[cur].laz2;
            tree[2*cur].laz1=tree[2*cur].laz1*tree[cur].laz2+tree[cur].laz1;
            changeII(2*cur+1,tree[cur].laz2);
            changeI(2*cur+1,tree[cur].laz1);
            tree[2*cur+1].laz2=tree[2*cur+1].laz2*tree[cur].laz2;
            tree[2*cur+1].laz1=tree[2*cur+1].laz1*tree[cur].laz2+tree[cur].laz1;
            tree[cur].laz1=0;
            tree[cur].laz2=1;
        }
    	return;
    }
     
    void build(int l,int r,int cur)
    {
        int m;
        tree[cur].l=l;
        tree[cur].r=r;
        tree[cur].val=0;
        tree[cur].laz1=0;
        tree[cur].laz2=1;
        if(l==r) return;
        m=(l+r)/2;
        build(l,m,2*cur);
        build(m+1,r,2*cur+1);
        pushup(cur);
    }
     
    void updateII(int op,int pl,int pr,ll val,int cur)
    {
        if(pl<=tree[cur].l&&tree[cur].r<=pr)
        {
            if(op==1)
            {
                changeI(cur,val);
                tree[cur].laz1+=val;
            }
            else
            {
                changeII(cur,val);
                tree[cur].laz2=tree[cur].laz2*val;
    			tree[cur].laz1=tree[cur].laz1*val;
            }
            return;
        }
        pushdown(cur);
        if(pl<=tree[2*cur].r) updateII(op,pl,pr,val,2*cur);
        if(pr>=tree[2*cur+1].l) updateII(op,pl,pr,val,2*cur+1);
        pushup(cur);
    }
     
    void updateI(int op,int u,int v,ll val)
    {
        while(top[u]!=top[v])
        {
            if(deep[top[u]]<deep[top[v]]) swap(u,v);
            updateII(op,mp1[top[u]],mp1[u],val,1);
            u=fa[top[u]];
        }
        if(deep[u]<deep[v]) swap(u,v);
        updateII(op,mp1[v],mp1[u],val,1);
        return;
    }
     
    ll queryII(int pl,int pr,int cur)
    {
        ll res;
        if(pl<=tree[cur].l&&tree[cur].r<=pr) return tree[cur].val;
        pushdown(cur);
        res=0;
        if(pl<=tree[2*cur].r) res+=queryII(pl,pr,2*cur);
        if(pr>=tree[2*cur+1].l) res+=queryII(pl,pr,2*cur+1);
        return res;
    }
     
    ll queryI(int u,int v)
    {
        ll res;
        res=0;
        while(top[u]!=top[v])
        {
            if(deep[top[u]]<deep[top[v]]) swap(u,v);
            res+=queryII(mp1[top[u]],mp1[u],1);
            u=fa[top[u]];
        }
        if(deep[u]<deep[v]) swap(u,v);
        res+=queryII(mp1[v],mp1[u],1);
        return res;
    }
     
    int main()
    {
        ll w;
        int i,op,u,v;
        while(scanf("%d",&n)!=EOF)
        {
            memset(first,-1,sizeof(first));
            num=0;
            for(i=2;i<=n;i++)
            {
                scanf("%d",&u);
                addedge(u,i);
                addedge(i,u);
            }
            fa[1]=0,deep[1]=1;
            dfsI(1);
            num=0;
            dfsII(1,1);
            build(1,n,1);
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d",&op);
                if(op==1)
                {
                    scanf("%d%d%llu",&u,&v,&w);
                    updateI(2,u,v,w);
                }
                else if(op==2)
                {
                    scanf("%d%d%llu",&u,&v,&w);
                    updateI(1,u,v,w);
                }
                else if(op==3)
                {
                    scanf("%d%d",&u,&v);
                    updateI(2,u,v,-1);
                    updateI(1,u,v,mod);
                }
                else
                {
                    scanf("%d%d",&u,&v);
                    printf("%llu
    ",queryI(u,v));
                }
            }
        }
        return 0;
    }
    
    
    

      












  • 相关阅读:
    HDU1698(线段树入门题)
    POJ2528(离散化+线段树区间更新)
    POJ3630(Trie树)
    HDU1251(字典树)
    HDU1247(经典字典树)
    POJ2513(字典树+图的连通性判断)
    POJ1363
    UVa11624(逃离火焰问题)
    HDOJ1495(倒水BFS)
    poj3414Pots(倒水BFS)
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11222111.html
Copyright © 2011-2022 走看看