Problem:
Multi-Set

For a set $S$ of integers, perform a sequence of the following operations. Note that multiple elements can have equivalent values in $S$.

insert($x$): Insert $x$ to $S$ and report the number of elements in $S$ after the operation.

find($x$): Report the number of $x$ in $S$.

delete($x$): Delete all $x$ from $S$.

dump($L$, $R$): Print elements $x$ in $S$ such that $L \leq x \leq R$.

Input

The input is given in the following format.

$q$
$query_1$
$query_2$
:
$query_q$

Each query $query_i$ is given by

0 $x$

or

1 $x$

or

2 $x$

or

3 $L$ $R$

where the first digits 0, 1, 2 and 3 represent insert, find, delete and dump operations respectively.

Output

For each insert operation, print the number of elements in $S$.

For each find operation, print the number of specified elements in $S$.

For each dump operation, print the corresponding elements in ascending order. Print an element in a line.

Constraints

$1 \leq q \leq 200,000$

$0 \leq x \leq 1,000,000,000$

The total number of elements printed by dump operations does not exceed $1,000,000$

The sum of numbers printed by find operations does not exceed $2,000,000$

Sample Input 1

10
0 1
0 1
0 2
0 3
2 2
1 1
1 2
1 3
0 4
3 1 4

Sample Output 1

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

Solution in JAVA (judge verdict: Wrong Answer)


import java.io.*;
import java.util.*;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner in=new Scanner (System.in);
        Mymset mset=new Mymset();
        int q=Integer.parseInt(in.next());
        for(int i=0;i<q;i++) {
            int odr=Integer.parseInt(in.next());
            switch(odr) {
            case 0:
                System.out.println(mset.insert(Integer.parseInt(in.next())));
                break;
                 
            case 1:
                System.out.println(mset.find(Integer.parseInt(in.next())));
                break;
                 
            case 2:
                mset.removeOf(Integer.parseInt(in.next()));
                break;
                 
            case 3:
                mset.dump(Integer.parseInt(in.next()),Integer.parseInt(in.next()));
                break;
            }
        }
    }
 
}
 
class Bnode{
    int v,num;
    Bnode p,l,r;
 
 
    Bnode(int v,int num){
        this.v=v;
        this.num=num;
    }
}
 
class Mymset{
    Bnode root,dummy,NOW;
    int size;
    PrintWriter out=new PrintWriter(System.out);
     
    Mymset(){
        dummy=new Bnode(-1,-1);
        dummy.p=dummy; dummy.l=dummy; dummy.r=dummy;
        init();
        size=0;
    }
 
    void init() {
        root=dummy;
    }
 
    int insert(int x) {
        Bnode NEW=new Bnode(x,1);
        NEW.l=dummy;NEW.r=dummy;
        if(size==0) {
            root=NEW;
            root.p=dummy;
        }
        else {
            //Bnode NOW=root;
            NOW=root;
            while(true) {
                if(NOW.v==NEW.v) {
                    NOW.num++;
                    break;
                }
                else if(NEW.v>NOW.v) {
                    if(NOW.r.v==-1) {
                        NOW.r=NEW;
                        NEW.p=NOW;
                        break;
                    }
                    else NOW=NOW.r;
                }
                else {
                    if(NOW.l.v==-1) {
                        NOW.l=NEW;
                        NEW.p=NOW;
                        break;
                    }
                    else NOW=NOW.l;
                }
            }
        }
        size++;
        return size;
    }
 
    void removeOf(int x){
        find(x);
        int n=NOW.num;
        if(NOW.r.v==-1 && NOW.l.v==-1){
            if(NOW.p.l==NOW)NOW.p.l=dummy;
            else NOW.p.r=dummy;
        }
        else if(NOW.r.v!=-1 || NOW.l.v!=-1) {
            if(NOW.p.r==NOW) {
                NOW.p.r=NOW.r;
                NOW.r.p=NOW.p;
            }
            else {
                NOW.p.l=NOW.l;
                NOW.l.p=NOW.p;
            }
        }
        else {
            Bnode y=findNextNode(NOW.r);
            NOW.v=y.v;
            NOW.num=y.num;
            if(y.r.v==-1 && y.l.v==-1){
                if(y.p.l==y)y.p.l=dummy;
                else y.p.r=dummy;
            }
            else if(y.r.v!=-1 || y.l.v!=-1) {
                if(y.p.r==y) {
                    y.p.r=y.r;
                    y.r.p=y.p;
                }
                else {
                    y.p.l=y.l;
                    y.l.p=y.p;
                }
            }
        }
        size-=n;
    }
     
     
    Bnode findNextNode(Bnode node) {
        if(node.l.v!=-1)return findNextNode(node.l);
        else return node;
    }
 
    int find(int x){
        NOW=root;
        while(NOW.v!=-1) {
 
            if(NOW.v==x)break;
            else if(NOW.v>x)NOW=NOW.l;
            else NOW=NOW.r;
        }
        return (NOW.num>0)?NOW.num : 0;
    }
 
    void dump(int L,int R) {
        inwalk(root,L,R);
        out.flush();
    }
 
    void inwalk(Bnode now,int L,int R) {
        if(now.v>=L && now.v<=R) {
            if(now.l.v!=-1)inwalk(now.l,L,R);
            for(int i=0;i<now.num;i++)out.println(now.v);
            if(now.r.v!=-1)inwalk(now.r,L,R);
        }
    }
 
}