ZJOI2016 forest

Large forest

Y home has a small forest, there \ (n \) tree, numbered from \ (1 \) to \ (n \) . These trees are just the beginning of a sapling, only one node, labeled \ (1 \) . These trees have a special node, which we call the growth nodes, which have the ability to grow out of child nodes. A small master Y magic, allows the first \ (L \) tree to the second \ (R & lt \) grow a child node of the node tree growth. She can also modify section \ (L \) tree to the second \ (R & lt \) growing the tree node. She told you she uses magic record, you can not manage the forests of her home and asked her to answer it?

Input

The first line contains \ (2 \) positive integer \ (n-, m \) , a total of \ (n-\) trees and \ (m \) operations. Next \ (m \) rows, each row comprising a plurality of non-negative integer operation, operating the format:

  • 0 l rShows a section \ (L \) tree to the second \ (R & lt \) growth of the tree nodes below to grow a child node, the reference node is a child \ (0 \) resolution operation leaves numeral plus \ (1 \ ) (e.g., a first \ (0 \) child node number generated by the operation designated \ (2 \) ), \ (L \) to \ (R & lt \) trees grow between the nodes the same reference numerals. Ensure \ (1≤l≤r≤n \) .
  • 1 l r xShows a section \ (L \) tree to the second \ (R & lt \) growing the tree node labeled changed to \ (X \) node. For \ (i (l≤i≤r) \) tree, if the label \ (X \) is the point where not, then this does not affect the operation of the tree. Ensure \ (1≤l≤r≤n \) , \ (the X-\) does not exceed the current maximum of all the nodes in the tree labels.
  • 2 x u vAsk first \ (X \) tree nodes \ (U \) to node \ (V \) from the point, i.e. at the \ (X \) tree node from \ (U \) and nodes \ ( v \) the number of the shortest side of the road. Ensure \ (1≤x≤n \) , this tree node \ (u \) and node \ (v \) exists.

\ (n \ leq 10 ^ 5, m \ leq 2 \ times 10 ^ 5 \) .

Output

It includes a plurality of output lines, the answer to a query sequence output Y of each small

Sample Input

5 5
0 1 5
1 2 4 2
0 1 4
2 1 1 3
2 2 1 3

Sample Output

1
2

answer

This problem gives two (10 ^ 5 \) \ level axis, a time axis, a tree is the axis number.

Obviously we need to do something so that we only deal with one axis in the same time.

Property Analysis

0 l rGrow each operation node number is allocated according to the number of operations; and if we add some redundancy node to a tree, then the distance between two points of the original will not change. So we can say that for each operation are global, i.e., \ (\ FORALL [L, R & lt] = [. 1, n-] \) .

1 x u vThe answer has nothing to do with the interrogation time, that it is not time-sensitive. So we can see it as the ultimate form of interrogation of the tree.

Then we can first deal with tree shape, reprocessing ask.

In fact, these two operations are above prompted us offline.

2 l r xThis operation is tricky. We first consider its impact on a tree.

Each operation is clearly affected node number belongs to a suffix \ ([l_i, n] \ ) growing point of those nodes. And assuming a plurality of operating simultaneously on a tree, then a growth point node 2 all influence its operation at the latest action.

In other words, the growing point of this provision is actually divided in the following figure:

forest

If we remove the impact of one of these two operations, then, in fact, the growing point where some of the provisions of the preceding paragraph it becomes a growing point requirements. Note changed little cause to do so, so that you can undo is performed.

So we can put the tree node number as the timeline, then the operation is equivalent to 2 \ (time = l_i \) when added to its impact, in \ (time = r_i + 1 \ ) remove its influence when. Delete to talk with the above method.

algorithm design

Scanning line to handle our imaginary axis.

Growing point for each predetermined operation is to build a virtual right adapter convenient point 0, all nodes are affected go out into a virtual point before it last longer.

After the end of the interval effect a virtual point of a virtual point to put the replacement on a growing point corresponding virtual points.

LCT can easily realize, time complexity \ (O (m \ log n-) \) .

Code

Usually when we calculate the distance between two points is to count the father side of each point. Only makeroot, access, splay, taken size-1.

But this problem which we can not do that. Because there are virtual points, while the father's side of the imaginary point actually does not exist, so the virtual point should not be included in the answer.

If only the real point (dotted) the weights assigned to 1 (0), then, since it is not aware of the real or virtual point at a point of LCA, obtained from not know (and weight) should not be -1 but it ended up requirements LCA.

To use as a direct x, distance y, LCA to the root (and weight) repellent capacity, so also do not need to write makerootand rev marker.

How to get the LCA it? Method is to access(x), after access(y), access(y)end of the chain when the last piece of combined chain is the LCA.

co int N=4e5+7;
int n,m,v[N],ch[N][2],p[N],sum[N],ans[N];
#define lc ch[x][0]
#define rc ch[x][1]
bool nroot(int x){return ch[p[x]][0]==x||ch[p[x]][1]==x;};
void update(int x){sum[x]=sum[lc]+v[x]+sum[rc];}
void rotate(int x){
    int y=p[x],z=p[y],l=x==ch[y][1],r=l^1;
    if(nroot(y)) ch[z][y==ch[z][1]]=x;p[x]=z;
    ch[y][l]=ch[x][r],p[ch[x][r]]=y;
    ch[x][r]=y,p[y]=x;
    update(y),update(x);
}
void splay(int x){
    for(int y,z;nroot(x);rotate(x)){
        y=p[x],z=p[y];
        if(nroot(y)) x==ch[y][1]^y==ch[z][1]?rotate(x):rotate(y);
    }
}
int access(int x){
    int t=0;
    for(;x;x=p[t=x])
        splay(x),rc=t,update(x);
    return t;
}
void lik(int x,int y){
    splay(x),p[x]=y;
}
void cut(int x){
    access(x),splay(x),p[lc]=0,lc=0,update(x);
}
int qry(int x,int y){
    int ans=0;
    access(x),splay(x),ans+=sum[x];
    int t=access(y);splay(y),ans+=sum[y];
    access(t),splay(t),ans-=2*sum[t];
    return ans;
}

struct node{
    int pos,op,x,y;
    bool operator<(co node&q)co{
        return pos^q.pos?pos<q.pos:op<q.op;
    }
}q[N];

int tot,last,id[N],idd,cnt,L[N],R[N],qs;
void newnode(int x){
    ++tot,v[tot]=x,sum[tot]=x;
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n),read(m);
    newnode(1),idd=1,L[1]=1,R[1]=n,id[1]=1;
    newnode(0),last=2,lik(2,1);
    for(int ti=1,o,l,r,x,u,v;ti<=m;++ti){
        read(o);
        if(o==0){
            read(l),read(r);
            newnode(1);
            L[++idd]=l,R[idd]=r,id[idd]=tot;
            q[++cnt]=(node){1,ti-m,tot,last};
        }
        else if(o==1){
            read(l),read(r),read(x);
            l=std::max(l,L[x]),r=std::min(r,R[x]);
            if(l<=r){
                newnode(0),lik(tot,last);
                q[++cnt]=(node){l,ti-m,tot,id[x]};
                q[++cnt]=(node){r+1,ti-m,tot,last};
                last=tot;
            }
        }
        else{
            read(x),read(u),read(v);
            q[++cnt]=(node){x,++qs,id[u],id[v]};
        }
    }
    std::sort(q+1,q+cnt+1);
    for(int i=1,j=1;i<=n;++i)
        for(;j<=cnt&&q[j].pos==i;++j){
            if(q[j].op<=0) cut(q[j].x),lik(q[j].x,q[j].y);
            else ans[q[j].op]=qry(q[j].x,q[j].y);
        }
    for(int i=1;i<=qs;++i) printf("%d\n",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/autoint/p/11938950.html