• Codechef Observing the Tree


    Home » Practice(Hard) » Observing the Tree
     

    Observing the Tree Problem Code: QUERYSolved

    Submit

    All submissions for this problem are available.

    Chef gives you a tree, consisting of N nodes. The nodes are numbered from 1 to N, and each node has an integer, which is equal to 0 initially. Then, Chef asks you to perform M queries.

    The first type of queries is changing: here, you are given integers X, Y, A and B. Add Ato the integer, associated with the node X, then add A+B to the integer, associated with the second node on the way from X to Y, then add A+2*B to the integer, associated with the third node on the way from X to Y, and so on. As you know, there is only one simple path from X to Y.

    The second type of queries is a question: here, you are given integers X and Y. Output the sum of all integers, associated with nodes on the way from X to Y.

    The third type of queries is a rollback: here, you are given an integer X. All the integers associated with the nodes return to the state after the X-th changing query. If X is 0, then all of them become equal to zero, as in the very beginning.

    Input

    The first line of an input consists of two integers - N and M.

    Then, N−1 lines follow. These N−1 lines describe the tree structure. Each line consists of two integers - X and Y, and that means that there is an edge between node X and node Y.

    Then, M lines follow. A single line denotes a single query, which has one of the following forms: (See the sample for the detailed explanation)

    • c X1 Y1 A B - changing query,
    • q X1 Y1 - question query,
    • l X1 - rollback query.

    As you can see, the numbers X and Y aren't given to you directly. For the rollbackquery, actual number X will be equal to (X1+lastans) modulo (total number ofchanging queries before this query + 1). For the changing and question queries, Xwill be equal to ((X1+lastans) modulo N)+1 and Y will be equal to ((Y1+lastans) modulo N)+1, where lastans denotes the last number that you have output, or zero if you haven't output any numbers yet.

    Output

    For each question query output the answer on a single line.

    Constraints

    • 1 ≤ N, M ≤ 100000 (105)
    • 0 ≤ A, B ≤ 1000
    • 0 ≤ X1, Y1 ≤ 100000 (105)

    Example

    Input:
    5 7
    1 2
    2 3
    3 4
    4 5
    c 1 4 2 3
    c 2 3 5 10
    q 1 3
    l 1
    q 1 3
    l 1
    q 1 3
    
    Output:
    35
    0
    15
    

    Explanation

    As you can see, the tree in the sample is like a line. Let's denote the first state of integers 0 0 0 0 0, where the i-th integer means the integer associated with the node i.

    In the first changing query "c 1 4 2 3", the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (4 + 0) modulo 5 + 1 = 5. Hence the state will be 0 2 5 8 11 after this query.

    After the second changing query "c 2 3 5 10", the state will be 0 2 10 23 11 for similar reason.

    In the next question query, the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (3 + 0) modulo 5 + 1 = 4. Hence the answer must be 2 + 10 + 23 = 35.

    In the first rollback query "l 1", the actual number is X = (1 + 35) modulo (2 + 1) = 36 modulo 3 = 0, since lastans = 36. Thus the state will be rollbacked to 0 0 0 0 0.

    Then the answer of the next question query "q 1 3" must be 0, because all integers are currently 0.

    In the second rollback query "l 1", the actual number is X = (1 + 0) modulo (2 + 1) = 1, since lastans = 0. Thus the state will be 0 2 5 8 11, which is the state after the firstchanging query.

    Then the answer of the last question query must be 2 + 5 + 8 = 15.

    题意:

    一棵树,3个操作:

    树上两点之间加一个等差数列,

    查询树上两点之间权值和,

    回到某次修改之后的状态

    思路:树链剖分+主席树

    #include<cstdio>
    #include<algorithm>
    #define N 100001
    using namespace std;
    int root[N],lc[N*300],rc[N*300];
    int fa[N],deep[N],bl[N],son[N],id[N],cnt;
    long long k[N*300],b[N*300],sum[N*300];
    int front[N],nxt[N*2],to[N*2],tot;
    long long A,B,QA,QB,ans;
    int QL,QR;
    int sum_chan,now,n,m;
    int read()
    {
        int x=0; char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
        return x;
    }
    struct  TREE
    {
        long long get_sum(long long kk,long long bb,int n)
        {
            return (bb+bb+kk*(n-1))*n/2;
        }
        void change(int y,int &x,int l,int r)
        {
            x=++tot;
            lc[x]=lc[y];
            rc[x]=rc[y];
            k[x]=k[y];
            b[x]=b[y];
            sum[x]=sum[y];
            if(l>=QL&&r<=QR)
            {
                sum[x]+=get_sum(QB,(l-QL)*QB+QA,r-l+1);
                k[x]+=QB;
                b[x]+=(l-QL)*QB+QA;
                return;
            }
            int ll=max(QL,l),rr=min(QR,r);
            sum[x]+=get_sum(QB,QA+QB*(ll-QL),rr-ll+1);
            int mid=l+r>>1;
            if(QL<=mid) change(lc[y],lc[x],l,mid);
            if(QR>mid) change(rc[y],rc[x],mid+1,r);
        }
        void query(int x,int l,int r)
        {
            if(!x) return;
            if(QL<=l&&QR>=r)
            {
                ans+=sum[x];
                return;
            }
            int ll=max(l,QL),rr=min(r,QR);
            ans+=get_sum(k[x],b[x]+k[x]*(ll-l),rr-ll+1);
            int mid=l+r>>1;
            if(QL<=mid) query(lc[x],l,mid);
            if(QR>mid) query(rc[x],mid+1,r);
        }
    }Tree;
    struct CHAIN
    {
        void add(int u,int v)
        {
            to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
            to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
        }
        void dfs1(int x,int f)
        {
            son[x]++;
            for(int i=front[x];i;i=nxt[i])
             if(to[i]!=f)
             {
                 fa[to[i]]=x;
                 deep[to[i]]=deep[x]+1;
                 dfs1(to[i],x);
                 son[x]+=son[to[i]];
             }
        }
        void dfs2(int x,int top)
        {
            id[x]=++cnt;
            bl[x]=top;
            int y=0;
            for(int i=front[x];i;i=nxt[i])
              if(to[i]!=fa[x]&&son[to[i]]>son[y])  y=to[i];
            if(!y) return;
            dfs2(y,top);
            for(int i=front[x];i;i=nxt[i])
             if(to[i]!=fa[x]&&to[i]!=y) dfs2(to[i],to[i]);
        }
        int LCA(int x,int y)
        {
            while(bl[x]!=bl[y])
            {
                if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
                x=fa[bl[x]];
            }
            if(deep[x]>deep[y]) return y;
            return x;
        }
        void change(int x,int y,int dis)
        {
            int l=0,r=dis;
            while(bl[x]!=bl[y])
            {
                if(deep[bl[x]]>deep[bl[y]])
                {
                    QL=id[bl[x]];  QR=id[x];
                    QA=A+(l+QR-QL)*B;
                    QB=-B;
                    Tree.change(root[sum_chan],root[sum_chan],1,n);
                    x=fa[bl[x]];
                    l+=QR-QL+1;
                }
                else
                {
                    QL=id[bl[y]]; QR=id[y];
                    QA=A+(r-(QR-QL))*B;
                    QB=B;
                    Tree.change(root[sum_chan],root[sum_chan],1,n);
                    y=fa[bl[y]];
                    r-=QR-QL+1;
                }
            }
            if(deep[x]<deep[y])
            {
                QL=id[x]; QR=id[y];
                QA=A+l*B;
                QB=B;
                Tree.change(root[sum_chan],root[sum_chan],1,n); 
            }
            else
            {
                QL=id[y]; QR=id[x];
                QA=A+r*B;
                QB=-B;
                Tree.change(root[sum_chan],root[sum_chan],1,n);
            }
        }
        void query(int x,int y)
        {
            while(bl[x]!=bl[y])
            {
                if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
                QL=id[bl[x]]; QR=id[x];
                Tree.query(root[now],1,n);
                x=fa[bl[x]];
            }
            if(deep[x]>deep[y]) swap(x,y);
            QL=id[x]; QR=id[y];
            Tree.query(root[now],1,n);
        }
    }Chain;
    int main()
    {
    /*freopen("data.txt","r",stdin);
        freopen("my.txt","w",stdout);*/
        n=read(); m=read();
        int u,v;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            Chain.add(u,v);
        }
        Chain.dfs1(1,0);
        Chain.dfs2(1,1);
        tot=0;  char ch[3]; int dis;
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]=='c')
            {
                root[++sum_chan]=root[now];
                u=read(); v=read(); A=read(); B=read();
                u=(u+ans)%n+1; v=(v+ans)%n+1;
                dis=deep[u]+deep[v]-2*deep[Chain.LCA(u,v)];
                Chain.change(u,v,dis);
                now=sum_chan;
            }
            else if(ch[0]=='q')
            {
                u=read(); v=read();
                u=(u+ans)%n+1; v=(v+ans)%n+1;
                ans=0;
                Chain.query(u,v);
                printf("%lld
    ",ans);
            }
            else
            {
                u=read();
                u=(u+ans)%(sum_chan+1);
                now=u;
            }
        }
    } 
  • 相关阅读:
    input type = file 上传图片转为base64
    vue-cli 搭建的项目,无法用本地IP访问
    js小数点精度问题
    虚拟机安装软件必备技术之一 --虚拟机快照技术
    Linux 关机命令总结
    查询模块错误排查
    - Oracle 闪回特性(FLASHBACK DATABASE)
    ORACLE密码过期,修改密码
    查看sql执行进度
    ORACLE CPU过高的sql查询
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6878607.html
Copyright © 2020-2023  润新知