Wherever the destination is, whoever we meet, let's render this song together.

On a Cartesian coordinate plane lies a rectangular stage of size w × h, represented by a rectangle with corners (0, 0), (w, 0), (w, h) and (0, h). It can be seen that no collisions will happen before one enters the stage.

On the sides of the stage stand n dancers. The i-th of them falls into one of the following groups: 

  * Vertical: stands at (xi, 0), moves in positive y direction (upwards); 
  * Horizontal: stands at (0, yi), moves in positive x direction (rightwards). 

<image>

According to choreography, the i-th dancer should stand still for the first ti milliseconds, and then start moving in the specified direction at 1 unit per millisecond, until another border is reached. It is guaranteed that no two dancers have the same group, position and waiting time at the same time.

When two dancers collide (i.e. are on the same point at some time when both of them are moving), they immediately exchange their moving directions and go on.

<image>

Dancers stop when a border of the stage is reached. Find out every dancer's stopping position.

Input

The first line of input contains three space-separated positive integers n, w and h (1 ≤ n ≤ 100 000, 2 ≤ w, h ≤ 100 000) — the number of dancers and the width and height of the stage, respectively.

The following n lines each describes a dancer: the i-th among them contains three space-separated integers gi, pi, and ti (1 ≤ gi ≤ 2, 1 ≤ pi ≤ 99 999, 0 ≤ ti ≤ 100 000), describing a dancer's group gi (gi = 1 — vertical, gi = 2 — horizontal), position, and waiting time. If gi = 1 then pi = xi; otherwise pi = yi. It's guaranteed that 1 ≤ xi ≤ w - 1 and 1 ≤ yi ≤ h - 1. It is guaranteed that no two dancers have the same group, position and waiting time at the same time.

Output

Output n lines, the i-th of which contains two space-separated integers (xi, yi) — the stopping position of the i-th dancer in the input.

Examples

Input

8 10 8
1 1 10
1 4 13
1 7 1
1 8 2
2 2 0
2 5 14
2 6 0
2 6 1


Output

4 8
10 5
8 8
10 6
10 2
1 8
7 8
10 6


Input

3 2 3
1 1 2
2 1 1
1 1 5


Output

1 3
2 1
1 3

Note

The first example corresponds to the initial setup in the legend, and the tracks of dancers are marked with different colours in the following figure.

<image>

In the second example, no dancers collide.
import java.awt.geom.Line2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Main2 {

    static long mod = 1000000007L;

    //in

    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        int n = scanner.nextInt();
        int w = scanner.nextInt();
        int h = scanner.nextInt();

        //List<Dancer> vertical = new ArrayList<>();
        Map<Integer, List<Dancer>> verticals = new HashMap<>();
        List<Dancer> horizontal = new ArrayList<>();
        List<Dancer> all = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            Dancer dancer = new Dancer(scanner.nextInt(), scanner.nextInt(), scanner.nextInt(), i);
            dancer.calcEnd(w, h);
            all.add(dancer);
            if (dancer.vertical) {
                verticals.computeIfAbsent(dancer.p - dancer.t, (kkk) -> new LinkedList<Dancer>()).add(dancer);
            } else horizontal.add(dancer);
        }
        for (List<Dancer> val : verticals.values()) {
            val.sort((d1, d2) -> d1.p - d2.p);
        }
        horizontal.sort((d1, d2) -> d1.p - d2.p);

        Pt[] result = new Pt[n];
        Map<Integer, LinkedList<Integer>> dancers = verticals.entrySet().stream()
                .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().stream().map(d -> d.num).collect(Collectors.toCollection(LinkedList::new))));

        for (Dancer hh : horizontal) {
            int key = hh.p - hh.t;
            LinkedList<Integer> intersect = dancers.get(key);
            if (intersect == null) {
                result[hh.num] = new Pt(hh.xe, hh.ye);
                continue;
            }
            intersect.push(hh.num);
            int res = intersect.pollLast();
            result[res] = new Pt(hh.xe, hh.ye);
        }

        for (Map.Entry<Integer, List<Dancer>> vert : verticals.entrySet()) {
            Iterator<Integer> order = dancers.get(vert.getKey()).iterator();
            for (Dancer d : vert.getValue()) {
                result[order.next()] = new Pt(d.xe, d.ye);
            }
        }

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < n; i++) {
            builder.append(result[i].xe).append(" ").append(result[i].ye).append("\n");
        }
        System.out.println(builder.toString());
    }

    static class Pt {
        int xe, ye;

        public Pt(int xe, int ye) {
            this.xe = xe;
            this.ye = ye;
        }
    }

    static class Dancer implements Comparable<Dancer> {
        int xe, ye;
        boolean vertical;
        int p, t;
        int num;

        public Dancer(int g, int p, int t, int num) {
            this.vertical = g == 1;
            this.p = p;
            this.t = t;
            this.num = num;
        }

        public void calcEnd(int w, int h) {
            if (vertical) {
                xe = p;
                ye = h;
            } else {
                xe = w;
                ye = p;
            }
        }

        @Override
        public int compareTo(Dancer o) {
            return Integer.compare(p + t, o.p + o.t) ;
        }
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String nextToken() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        String nextLine() {
            try {
                return br.readLine();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        long nextLong() {
            return Long.parseLong(nextToken());
        }

        double nextDouble() {
            return Double.parseDouble(nextToken());
        }

        int[] nextIntArray(int n) {
            int[] res = new int[n];
            for (int i = 0; i < n; i++) res[i] = nextInt();
            return res;
        }

        long[] nextLongArray(int n) {
            long[] res = new long[n];
            for (int i = 0; i < n; i++) res[i] = nextLong();
            return res;
        }

        String[] nextStringArray(int n) {
            String[] res = new String[n];
            for (int i = 0; i < n; i++) res[i] = nextToken();
            return res;
        }
    }

    static class PrefixSums {
        long[] sums;

        public PrefixSums(long[] sums) {
            this.sums = sums;
        }

        public long sum(int fromInclusive, int toExclusive) {
            if (fromInclusive > toExclusive) throw new IllegalArgumentException("Wrong sum");
            return sums[toExclusive] - sums[fromInclusive];
        }

        public static PrefixSums of(int[] ar) {
            long[] sums = new long[ar.length + 1];
            for (int i = 1; i <= ar.length; i++) {
                sums[i] = sums[i - 1] + ar[i - 1];
            }
            return new PrefixSums(sums);
        }

        public static PrefixSums of(long[] ar) {
            long[] sums = new long[ar.length + 1];
            for (int i = 1; i <= ar.length; i++) {
                sums[i] = sums[i - 1] + ar[i - 1];
            }
            return new PrefixSums(sums);
        }
    }

    static class ADUtils {
        static void sort(int[] ar) {
            Random rnd = ThreadLocalRandom.current();
            for (int i = ar.length - 1; i > 0; i--)
            {
                int index = rnd.nextInt(i + 1);
                // Simple swap
                int a = ar[index];
                ar[index] = ar[i];
                ar[i] = a;
            }
            Arrays.sort(ar);
        }

        static void sort(long[] ar) {
            Random rnd = ThreadLocalRandom.current();
            for (int i = ar.length - 1; i > 0; i--)
            {
                int index = rnd.nextInt(i + 1);
                // Simple swap
                long a = ar[index];
                ar[index] = ar[i];
                ar[i] = a;
            }
            Arrays.sort(ar);
        }
    }

    static class MathUtils {
        static long modpow(long b, long e, long m) {
            long result = 1;

            while (e > 0) {
                if ((e & 1) == 1) {
            /* multiply in this bit's contribution while using modulus to keep
             * result small */
                    result = (result * b) % m;
                }
                b = (b * b) % m;
                e >>= 1;
            }

            return result;
        }
    }
}