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\n",ans);
        }
        else
        {
            u=read();
            u=(u+ans)%(sum_chan+1);
            now=u;
        }
    }
} 

 

posted @ 2017-05-19 15:23  TRTTG  阅读(329)  评论(0编辑  收藏  举报