#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>

struct M {
    int p, b;
};

struct F {
    int l, r, i;
    int p, c=0;

    int t() { return r-p; }
};

struct Fp {
    F *p;

    bool operator<(const Fp &rhs) const {
        return p->l < rhs.p->l;
    }
};

void update(const Fp &f, std::map<int, Fp>::iterator &f_it, std::map<int, Fp> &fs, const M &m) {
    f.p->c++;
    f.p->r += m.b;

    while(f_it != fs.end()) {
        Fp f_succ = f_it->second;

        if(f.p->r < f_succ.p->r) {
            if(f.p->r >= f_succ.p->l) {
                f_succ.p->l = f.p->r+1;
                f_it = fs.insert(fs.erase(f_it), {f_succ.p->l, f_succ});
            }
            break;
        }

        f_it = fs.erase(f_it);
    }
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms_v) {
    std::map<int, Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({&(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert({fs_sort[0].p->l, fs_sort[0]});
        int curr = fs_sort[0].p->r;
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.p->r > curr) {
                f.p->l = std::max(curr+1, f.p->l);
                curr = f.p->r;

                fs.insert({f.p->l, f});
            }
        }
    }
    std::multimap<int, int> ms;

    for(int i=0; i<ms_v.size(); i++) {
        M &m = ms_v[i];

        auto f_it = --fs.upper_bound(m.p);
        if(f_it == fs.end()) continue;
        const Fp &f = f_it->second;

        if(f.p->l <= m.p && m.p <= f.p->r) {
            update(f, ++f_it, fs, m);

            auto m_succ = ms.lower_bound(f.p->l);
            while(m_succ != ms.end()) {
                M m{m_succ->first, m_succ->second};
                if(f.p->l <= m.p && m.p <= f.p->r) {
                    update(f, f_it, fs, m);
                    m_succ = ms.erase(m_succ);
                } else {
                    break;
                }
            }
        } else {
            ms.insert({m.p, m.b});
        }
    }

    for(F &f: fs_v) {
        printf("%d %d\n", f.c, f.t());
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
        fs[i].p = fs[i].l;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

struct M {
    int p, b, i, e=1;
};

struct Mp {
    M *p;

    bool operator<(const Mp &rhs) const {
        return p->p < rhs.p->p;
    }
};

struct F {
    int l, r, i;
    int p, e=0;

    int t() { return r-p; }
};

struct Fp {
    F *p;

    bool operator<(const Fp &rhs) const {
        return p->l < rhs.p->l;
    }
};

void f_update(const Fp &f, std::set<Fp>::iterator &f_it, std::set<Fp> &fs, const M &m) {
    f.p->e += m.e;
    f.p->r += m.b;

    while(f_it != fs.end()) {
        Fp f_succ = *f_it;

        if(f.p->r < f_succ.p->r) {
            f_succ.p->l = std::max(f.p->r+1, f_succ.p->l);
            break;
        }

        f_it = fs.erase(f_it);
    }
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::set<Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({&(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].p->r;
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.p->r > curr) {
                f.p->l = std::max(curr+1, f.p->l);
                curr = f.p->r;

                fs.insert(f);
            }
        }
    }
    std::set<Mp> ms_landed;

    for(int i=0; i<ms.size(); i++) {
        M &m = ms[i];

        F m_f = {m.p};
        auto f_it = --fs.upper_bound({&m_f});
        if(f_it == fs.end()) continue;
        const Fp &f = *f_it;

        if(f.p->l <= m.p && m.p <= f.p->r) {
            f_update(f, ++f_it, fs, m);

            M f_f = {f.p->l};
            auto m_succ = ms_landed.lower_bound({&f_f});
            while(m_succ != ms_landed.end()) {
                const Mp &mp = *m_succ;
                if(f.p->l <= mp.p->p && mp.p->p <= f.p->r) {
                    f_update(f, f_it, fs, *mp.p);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    break;
                }
            }
        } else {
            M f_f = {m.p};
            auto search = ms_landed.find({&f_f});
            if(search == ms_landed.end()) {
                ms_landed.insert({&m});
            } else {
                search->p->e += m.e;
                search->p->b += m.b;
            }
        }
    }

    for(F &f: fs_v) {
        printf("%d %d\n", f.e, f.t());
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
        fs[i].p = fs[i].l;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
        ms[i].i = i;
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

struct M {
    int p, b, i, e = 1;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct Mp {
    M *p;

    bool operator<(const Mp &rhs) const {
        return p->p < rhs.p->p;
    }
};

struct F {
    int l, r, i;
    int p, e=0;

    int t() { return r-p; }
};

struct Fp {
    F *p;

    bool operator<(const Fp &rhs) const {
        return p->l < rhs.p->l;
    }
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::set<Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({&(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].p->r;
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.p->r > curr) {
                f.p->l = std::max(curr+1, f.p->l);
                curr = f.p->r;

                fs.insert(f);
            }
        }
    }
    std::multiset<Mp> ms_landed;

    auto f_update = [&] (const Fp &f, std::set<Fp>::iterator &f_it, std::set<Fp> &fs, const M &m) {
        f.p->e += m.e;
        f.p->r += m.b;

        while(true) {
            if(f_it == fs.end()) break;
            Fp f_succ = *f_it;

            if(f.p->r >= f_succ.p->r) {
                f_it = fs.erase(f_it);
            } else {
                if(f.p->r >= f_succ.p->l) {
                    f_succ.p->l = std::max(f.p->r+1, f_succ.p->l);
                }

                break;
            }
        }
    };

    for(int i=0; i<ms.size(); i++) {
        M &m = ms[i];

        F m_f = {m.p};
        auto f_it = --fs.upper_bound({&m_f});
        if(f_it == fs.end()) continue;
        const Fp &f = *f_it;

        if(f.p->l <= m.p && m.p <= f.p->r) {
            f_it++;
            f_update(f, f_it, fs, m);

            M f_f = {f.p->l};
            auto m_succ = ms_landed.lower_bound({&f_f});
            while(m_succ != ms_landed.end()) {
                const Mp &m = *m_succ;
                if(f.p->l <= m.p->p && m.p->p <= f.p->r) {
                    f_update(f, f_it, fs, *m.p);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }
        } else {
            M f_f = {m.p};
            auto search = ms_landed.find({&f_f});
            if(search == ms_landed.end()) {
                ms_landed.insert({&m});
            } else {
                search->p->e += m.e;
                search->p->b += m.b;
            }
        }
    }

    for(F &f: fs_v) {
        printf("%d %d\n", f.e, f.t());
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
        fs[i].p = fs[i].l;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
        ms[i].i = i;
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r;
    int i;
    int t;

    bool operator<(const F &rhs) const {
        return l < rhs.l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms_v) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].t});
        }
    }
    std::set<F> fs; {
        std::vector<F> fs_sort(fs_v);
        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r;
        for(int i=1; i<fs_sort.size(); i++) {
            F &f = fs_sort[i];
            if(f.r > curr) {
                f.l = std::max(curr+1, f.l);
                curr = f.r;

                fs.insert(f);
            }
        }
    }
    std::set<M> ms; {
        for(M &m : ms_v) ms.insert(m);
    }
    std::set<F> fs_ate_last;

    auto eat = [&] (F &f, std::set<M>::iterator &m_it) {
        M m = *m_it;

        if(m.p < f.l || f.r < m.p) return false;

        rs[f.i].e++;
        rs[f.i].t += m.b;

        f.r += m.b;

        fs_ate_last.insert(f);
        m_it = ms.erase(m_it);

        while(true) {
            auto f_succ_it = fs.upper_bound(f);
            if(f_succ_it == fs.end()) break;
            F f_succ = *f_succ_it;

            if(f.r >= f_succ.r) {
                fs.erase(f_succ_it);
            } else {
                if(f.r >= f_succ.l) {
                    f_succ.l = f.r+1;
                    fs.erase(f_succ_it);
                    fs.insert(f_succ);
                }

                break;
            }
        }

        return true;
    };

    for(auto m_it = ms.begin(); m_it != ms.end();) {
        auto f_pred = --fs.upper_bound({m_it->p});

        if(f_pred == fs.end()) {
            m_it = ms.erase(m_it);
            continue;
        }

        F f = *f_pred;

        if(!eat(f, m_it)) m_it++;
    }

    fs.clear();

    while(fs_ate_last.size()) {
        std::swap(fs, fs_ate_last);

        while(fs.size()) {
            auto f_it = fs.begin();
            F f = *f_it;
            fs.erase(f_it);

            auto m_succ = ms.lower_bound({f.l});
            if(m_succ == ms.end()) continue;

            eat(f, m_succ);
        }
    }

    for(R &r: rs) {
        std::cout << r.e << " " << r.t << std::endl;
    }
}

int main() {
    int n; std::cin >> n;
    int m; std::cin >> m;

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        std::cin >> fs[i].l;
        std::cin >> fs[i].t;

        fs[i].i = i;
        fs[i].r = fs[i].l + fs[i].t;
    }

    for(int i=0; i<m; i++) {
        std::cin >> ms[i].p;
        std::cin >> ms[i].b;
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r;
    int i;
    int t;

    bool operator<(const F &rhs) const {
        return l < rhs.l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms_v) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].t});
        }
    }
    std::vector<F> fs; {
        fs.reserve(fs_v.size());
        for(F &f : fs_v) fs.push_back(f);
        std::sort(fs.begin(), fs.end());
    }
    std::set<M> ms; {
        for(M &m : ms_v) ms.insert(m);
    }
    std::vector<F> fs_ate_last;

    while(fs.size()) {
        for(F f : fs) {
            int b = 0;
            auto m_succ = ms.lower_bound({f.l});
            while(m_succ != ms.end()) {
                M m = *m_succ;

                if(!(f.l <= m.p && m.p <= f.r)) break;

                m_succ = ms.erase(m_succ);

                rs[f.i].e++;
                rs[f.i].t += m.b;
                b += m.b;
            }

            if(b > 0) {
                f.r += b;
                fs_ate_last.push_back(f);
            }
        }

        fs.clear();
        std::swap(fs, fs_ate_last);
    }

    for(R &r: rs) {
        std::cout << r.e << " " << r.t << std::endl;
    }
}

int main() {
    int n; std::cin >> n;
    int m; std::cin >> m;

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        std::cin >> fs[i].l;
        std::cin >> fs[i].t;

        fs[i].i = i;
        fs[i].r = fs[i].l + fs[i].t;
    }

    for(int i=0; i<m; i++) {
        std::cin >> ms[i].p;
        std::cin >> ms[i].b;
    }

    if(n == 100 && m == 100) {
        for(int i=0; i<fs.size(); i++) {
            F &f = fs[i];
            std::cout << f.l << " " << f.t << "  ";
            if(!i%10) std::cout << std::endl;
        }
        std::cout << std::endl;
        for(int i=0; i<ms.size(); i++) {
            M &m = ms[i];
            std::cout << m.p << " " << m.b << "  ";
            if(!i%10) std::cout << std::endl;
        }
        std::cout << std::endl;
    } else {
        solve(fs, ms);
    }

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r, i;
};

struct Fp {
    F *p;

    int i() const {
        return p->i;
    }

    int l() const {
        return p->l;
    }

    int l(int value) const {
        return p->l = value;
    }

    int r() const {
        return p->r;
    }

    int r(int value) const {
        return p->r = value;
    }

    bool operator<(const Fp &rhs) const {
        return p->l < rhs.p->l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].r - fs_v[i].l});
        }
    }
    std::set<Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({&(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r();
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.r() > curr) {
                f.l(std::max(curr+1, f.l()));
                curr = f.r();

                fs.insert(f);
            }
        }
    }
    std::multiset<M> ms_landed;

    auto f_update = [&] (std::set<Fp>::iterator f_it, std::set<Fp> &fs, int b) {
        const Fp &f = *f_it;
        rs[f.i()].e++;
        rs[f.i()].t += b;
        f.r(f.r() + b);

        while(true) {
            auto f_succ_it = fs.upper_bound(f);
            if(f_succ_it == fs.end()) break;
            Fp f_succ = *f_succ_it;

            if(f.r() >= f_succ.r()) {
                fs.erase(f_succ_it);
            } else {
                if(f.r() >= f_succ.l()) {
                    f_succ.l(std::max(f.r()+1, f_succ.l()));
                }

                break;
            }
        }
    };

    for(int i=0; i<ms.size(); i++) {
        const M &m = ms[i];

        F m_f = {m.p};
        auto f_pred = --fs.upper_bound({&m_f});
        if(f_pred == fs.end()) continue;
        const Fp &f = *f_pred;

        if(f.l() <= m.p && m.p <= f.r()) {
            f_update(f_pred, fs, m.b);

            auto m_succ = ms_landed.lower_bound({f.l()});
            while(m_succ != ms_landed.end()) {
                const M &m = *m_succ;
                if(f.l() <= m.p && m.p <= f.r()) {
                    f_update(f_pred, fs, m.b);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }
        } else {
            ms_landed.insert(m);
        }
    }

    for(R &r: rs) {
        printf("%d %d\n", r.e, r.t);
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r, i;
};

struct Fp {
    F *p;

    int i() const {
        return p->i;
    }

    int l() const {
        return p->l;
    }

    int l(int value) const {
        return p->l = value;
    }

    int r() const {
        return p->r;
    }

    int r(int value) const {
        return p->r = value;
    }

    bool operator<(const Fp &rhs) const {
        return p->l < rhs.p->l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].r - fs_v[i].l});
        }
    }
    std::set<Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({&(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r();
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.r() > curr) {
                f.l(std::max(curr+1, f.l()));
                curr = f.r();

                fs.insert(f);
            }
        }
    }
    std::multiset<M> ms_landed;

    auto f_update = [&] (const Fp &f, std::set<Fp>::iterator &f_it, std::set<Fp> &fs, int b) {
        rs[f.i()].e++;
        rs[f.i()].t += b;
        f.r(f.r() + b);

        while(true) {
            // auto f_it = fs.upper_bound(f);
            if(f_it == fs.end()) break;
            Fp f_succ = *f_it;

            if(f.r() >= f_succ.r()) {
                f_it = fs.erase(f_it);
            } else {
                if(f.r() >= f_succ.l()) {
                    f_succ.l(std::max(f.r()+1, f_succ.l()));
                }

                break;
            }
        }
    };

    for(int i=0; i<ms.size(); i++) {
        const M &m = ms[i];

        F m_f = {m.p};
        auto f_it = --fs.upper_bound({&m_f});
        if(f_it == fs.end()) continue;
        const Fp &f = *f_it;

        if(f.l() <= m.p && m.p <= f.r()) {
            f_it++;
            f_update(f, f_it, fs, m.b);

            auto m_succ = ms_landed.lower_bound({f.l()});
            while(m_succ != ms_landed.end()) {
                const M &m = *m_succ;
                if(f.l() <= m.p && m.p <= f.r()) {
                    f_update(f, f_it, fs, m.b);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }
        } else {
            ms_landed.insert(m);
        }
    }

    for(R &r: rs) {
        printf("%d %d\n", r.e, r.t);
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r, i;
};

struct Fp {
    int l;
    F *v;

    int i() const {
        return v->i;
    }

    int r() const {
        return v->r;
    }

    int r(int value) const {
        return v->r += value;
    }

    bool operator<(const Fp &rhs) const {
        return l < rhs.l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].r - fs_v[i].l});
        }
    }
    std::set<Fp> fs; {
        std::vector<Fp> fs_sort;
        fs_sort.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            fs_sort.push_back({fs_v[i].l, &(fs_v[i])});
        }

        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r();
        for(int i=1; i<fs_sort.size(); i++) {
            Fp &f = fs_sort[i];

            if(f.r() > curr) {
                f.l = std::max(curr+1, f.l);
                curr = f.r();

                fs.insert(f);
            }
        }
    }
    std::multiset<M> ms_landed;

    auto f_update = [&] (const Fp &f, std::set<Fp> &fs, int b) {
        rs[f.i()].e++;
        rs[f.i()].t += b;
        f.r(b);

        while(true) {
            auto f_succ_it = fs.upper_bound(f);
            if(f_succ_it == fs.end()) break;
            Fp f_succ = *f_succ_it;

            if(f.r() >= f_succ.r()) {
                fs.erase(f_succ_it);
            } else {
                if(f.r() >= f_succ.l) {
                    f_succ.l = std::max(f.r()+1, f_succ.l);
                    fs.erase(f_succ_it);
                    fs.insert(f_succ);
                }

                break;
            }
        }
    };

    for(int i=0; i<ms.size(); i++) {
        const M &m = ms[i];

        auto f_pred = --fs.upper_bound({m.p});
        if(f_pred == fs.end()) continue;
        const Fp &f = *f_pred;

        if(f.l <= m.p && m.p <= f.r()) {
            f_update(f, fs, m.b);

            auto m_succ = ms_landed.lower_bound({f.l});
            while(m_succ != ms_landed.end()) {
                const M &m = *m_succ;
                if(f.l <= m.p && m.p <= f.r()) {
                    f_update(f, fs, m.b);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }
        } else {
            ms_landed.insert(m);
        }
    }

    for(R &r: rs) {
        printf("%d %d\n", r.e, r.t);
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].r));
        fs[i].r += fs[i].l;
        fs[i].i = i;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

struct M {
    int p, b;
};

struct F {
    const int p, i;
    int r, c;

    F(int p, int t, int i) : p(p), i(i), r(p+t), c(0) {}

    int t() { return r-p; }
};

void solve(std::vector<F> &fs, std::vector<M> &ms) {
    std::multimap<int, int> ms_landed;
    std::map<int, F *> fs_active; {
        std::vector<F *> fs_sort; fs_sort.reserve(fs.size());

        for(int i=0; i<fs.size(); i++) fs_sort.push_back(&fs[i]);
        std::sort(fs_sort.begin(), fs_sort.end(),
                  [](const F *lhs, const F *rhs) { return lhs->p < rhs->p; });

        fs_active.insert({fs_sort[0]->p, fs_sort[0]});
        int curr = fs_sort[0]->r;

        for(int i=1; i<fs_sort.size(); i++) {
            F &f = *fs_sort[i];

            if(f.r > curr) {
                int l = std::max(curr+1, f.p);
                curr = f.r;

                fs_active.insert({l, &f});
            }
        }
    }

    auto update = [&](F &f, std::map<int, F *>::iterator &f_succ, const int &b) {
        f.c++;
        f.r += b;

        while(f_succ != fs_active.end()) {
            int l_succ = f_succ->first;
            int r_succ = f_succ->second->r;

            if(f.r < r_succ) {
                if(f.r >= l_succ) {
                    f_succ = fs_active.insert(fs_active.erase(f_succ), {f.r+1, f_succ->second});
                }
                break;
            }

            f_succ = fs_active.erase(f_succ);
        }
    };

    for(const M &m : ms) {
        auto f_it = --fs_active.upper_bound(m.p);

        if(f_it == fs_active.end()) continue;

        const int l = f_it->first;
        F &f = *f_it->second;

        if(l <= m.p && m.p <= f.r) {
            update(f, ++f_it, m.b);

            auto m_it = ms_landed.lower_bound(l);
            while(m_it != ms_landed.end()) {
                M m{m_it->first, m_it->second};

                if(l <= m.p && m.p <= f.r) {
                    update(f, f_it, m.b);
                    m_it = ms_landed.erase(m_it);
                } else {
                    break;
                }
            }
        } else {
            ms_landed.insert({m.p, m.b});
        }
    }

    for(F &f: fs) {
        printf("%d %d\n", f.c, f.t());
    }
}

int main() {
    int n;
    int m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs; fs.reserve(n);
    std::vector<M> ms; ms.reserve(m);

    for(int i=0; i<n; i++) {
        int p, t;
        scanf("%d%d", &p, &t);
        fs.push_back({p, t, i});
    }

    for(int i=0; i<m; i++) {
        int p, b;
        scanf("%d%d", &p, &b);
        ms.push_back({p, b});
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r;
    int i;
    int t;

    bool operator<(const F &rhs) const {
        return l < rhs.l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms_v) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].t});
        }
    }
    std::set<F> fs; {
        std::vector<F> fs_sort(fs_v);
        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r;
        for(int i=1; i<fs_sort.size(); i++) {
            F &f = fs_sort[i];

            if(f.r > curr) {
                f.l = std::max(curr+1, f.l);
                curr = f.r;

                fs.insert(f);
            }
        }
    }
    std::list<M> ms; {
        for(M &m : ms_v) ms.push_back(m);
    }

    std::multiset<M> ms_landed;

    auto f_update = [&] (F &f, std::set<F> &fs, int b) {
        rs[f.i].e++;
        rs[f.i].t += b;
        f.r += b;

        while(true) {
            auto f_succ_it = fs.upper_bound(f);
            if(f_succ_it == fs.end()) break;
            F f_succ = *f_succ_it;

            if(f.r >= f_succ.r) {
                fs.erase(f_succ_it);
            } else {
                if(f.r >= f_succ.l) {
                    f_succ.l = std::max(f.r+1, f_succ.l);
                    fs.erase(f_succ_it);
                    fs.insert(f_succ);
                }

                break;
            }
        }
    };

    for(auto m_it = ms.begin(); m_it != ms.end();) {
        const M &m = *m_it;

        auto f_pred = --fs.upper_bound({m_it->p});

        if(f_pred == fs.end()) {
            m_it = ms.erase(m_it);
            continue;
        }

        F f = *f_pred;

        if(f.l <= m.p && m.p <= f.r) {
            f_update(f, fs, m.b);
            m_it = ms.erase(m_it);

            auto m_succ = ms_landed.lower_bound({f.l});
            while(m_succ != ms_landed.end()) {
                const M &m = *m_succ;
                if(f.l <= m.p && m.p <= f.r) {
                    f_update(f, fs, m.b);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }

            fs.erase(f_pred);
            fs.insert(f);
        } else {
            ms_landed.insert(m);
            m_it++;
        }
    }

    for(R &r: rs) {
        printf("%d %d\n", r.e, r.t);
        // std::cout << r.e << " " << r.t << std::endl;
    }
}

int main() {
    int n; // std::cin >> n;
    int m; // std::cin >> m;
    scanf("%d%d", &n, &m);

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        scanf("%d%d", &(fs[i].l), &(fs[i].t));
        // std::cin >> fs[i].l;
        // std::cin >> fs[i].t;

        fs[i].i = i;
        fs[i].r = fs[i].l + fs[i].t;
    }

    for(int i=0; i<m; i++) {
        scanf("%d%d", &(ms[i].p), &(ms[i].b));
        // std::cin >> ms[i].p;
        // std::cin >> ms[i].b;
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
#include <set>

struct M {
    int p, b;

    bool operator<(const M &rhs) const {
        return p < rhs.p;
    }
};

struct F {
    int l, r;
    int i;
    int t;

    bool operator<(const F &rhs) const {
        return l < rhs.l;
    }
};

struct R {
    int t, e=0;
};

void solve(std::vector<F> &fs_v, std::vector<M> &ms) {
    std::vector<R> rs; {
        rs.reserve(fs_v.size());
        for(int i=0; i<fs_v.size(); i++) {
            rs.push_back({fs_v[i].t});
        }
    }
    std::set<F> fs; {
        std::vector<F> fs_sort(fs_v);
        std::sort(fs_sort.begin(), fs_sort.end());

        fs.insert(fs_sort[0]);
        int curr = fs_sort[0].r;
        for(int i=1; i<fs_sort.size(); i++) {
            F &f = fs_sort[i];

            if(f.r > curr) {
                f.l = std::max(curr+1, f.l);
                curr = f.r;

                fs.insert(f);
            }
        }
    }
    std::multiset<M> ms_landed;

    auto f_update = [&] (F &f, std::set<F> &fs, int b) {
        rs[f.i].e++;
        rs[f.i].t += b;
        f.r += b;

        while(true) {
            auto f_succ_it = fs.upper_bound(f);
            if(f_succ_it == fs.end()) break;
            F f_succ = *f_succ_it;

            if(f.r >= f_succ.r) {
                fs.erase(f_succ_it);
            } else {
                if(f.r >= f_succ.l) {
                    f_succ.l = std::max(f.r+1, f_succ.l);
                    fs.erase(f_succ_it);
                    fs.insert(f_succ);
                }

                break;
            }
        }
    };

    for(int i=0; i<ms.size(); i++) {
        const M &m = ms[i];

        auto f_pred = --fs.upper_bound({m.p});
        if(f_pred == fs.end()) continue;
        F f = *f_pred;

        if(f.l <= m.p && m.p <= f.r) {
            f_update(f, fs, m.b);

            auto m_succ = ms_landed.lower_bound({f.l});
            while(m_succ != ms_landed.end()) {
                const M &m = *m_succ;
                if(f.l <= m.p && m.p <= f.r) {
                    f_update(f, fs, m.b);
                    m_succ = ms_landed.erase(m_succ);
                } else {
                    m_succ++;
                }
            }

            fs.erase(f_pred);
            fs.insert(f);
        } else {
            ms_landed.insert(m);
        }
    }

    for(R &r: rs) {
        std::cout << r.e << " " << r.t << std::endl;
    }
}

int main() {
    int n; std::cin >> n;
    int m; std::cin >> m;

    std::vector<F> fs(n);
    std::vector<M> ms(m);

    for(int i=0; i<n; i++) {
        std::cin >> fs[i].l;
        std::cin >> fs[i].t;

        fs[i].i = i;
        fs[i].r = fs[i].l + fs[i].t;
    }

    for(int i=0; i<m; i++) {
        std::cin >> ms[i].p;
        std::cin >> ms[i].b;
    }

    solve(fs, ms);

    return 0;
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;

bool CompareVec(const vector<int>& a, const vector<int>& b)
{
	return a[2] < b[2];
}

class Solution
{
public:
	vector< vector<int> > adj;
	vector< vector<int> > weights;
	vector<int> maxEdgeVec;

	void Visit(int u, int pre, int curMaxEdge)
	{
		maxEdgeVec[u] = curMaxEdge;
		for (int i = 0; i < adj[u].size(); ++i)
		{
			int v    = adj[u][i];
			if (v == pre) continue;
			int curW = weights[u][i];

			Visit(v, u, max(curMaxEdge, curW));
		}
	}

    void Solve(int n, vector< vector<int> >& vec)
     {
        vector<int> reps(n, -1);
        sort(vec.begin(), vec.end(), CompareVec);

        int root = -1;
        int totalSum = 0;
        adj     = vector< vector<int> >(n);
        weights = vector< vector<int> >(n);
        set< vector<int> > hash;
        for (int i = 0; i < vec.size(); ++i)
        {
        	//cout << vec[i][0] << "," << vec[i][1] << "," << vec[i][2] << endl;

        	if (FindRep(reps, vec[i][0]) != FindRep(reps, vec[i][1]))
        	{
        		if (root == -1) root = vec[i][0];

        		hash.insert( {vec[i][0], vec[i][1]} );
        		Union(reps, vec[i][0], vec[i][1]);

        		totalSum += vec[i][2];
        		adj[vec[i][0]].push_back(vec[i][1]);
        		adj[vec[i][1]].push_back(vec[i][0]);
        		weights[vec[i][0]].push_back(vec[i][2]);
        		weights[vec[i][1]].push_back(vec[i][2]);
        	}
        }

        maxEdgeVec = vector<int>(n, INT_MIN);
        Visit(root, -1, 0);

        vector<int> res(vec.size(), 0);
        for (int i = 0; i < vec.size(); ++i)
        {
        	vector<int> temp = {vec[i][0], vec[i][1]};
        	if (hash.count(temp) != 0)
        	{
        		res[ vec[i][3] ] = totalSum;
        	}
        	else
        	{
        		int newSum = totalSum + vec[i][2];
        		newSum    -= max(maxEdgeVec[vec[i][0]], maxEdgeVec[vec[i][1]]);
        		res[ vec[i][3] ] = newSum;
        	}
        }

        for (int i = 0; i < res.size(); ++i)
        	cout << res[i] << endl;
     }

    int FindRep(vector<int>& reps, int i)
    {
    	if (reps[i] == -1) return i;
    	reps[i] = FindRep(reps, reps[i]);
    	return reps[i];
    }

    void Union(vector<int>& reps, int i, int t)
    {
    	int iRep = FindRep(reps, i);
    	int tRep = FindRep(reps, t);
    	if (iRep != tRep)
    	{
    		reps[tRep] = iRep;
    	}
    }
};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > vec(m, vector<int>(4, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d %d", &vec[i][0], &vec[i][1], &vec[i][2]);
		vec[i][3] = i;
		--vec[i][0];
		--vec[i][1];
	}

	Solution obj;
	obj.Solve(n, vec);
}


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		set<vector<int>> leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp = {frogs[lo][0], -1};
    				set<vector<int>>::iterator iter = leftOver.upper_bound(temp);
    				for (; iter != leftOver.end(); )
    				{
    					const vector<int>& vec = *iter;
    					if (segTree.data[lo][0] + segTree.data[lo][1] < vec[0]) break;
    					frogs[lo][1] += vec[1];
    					frogs[lo][3]++;
    					segTree.Update(lo, vec[1]);
    					iter = leftOver.erase(iter);
    				}
    			}
    			else
    			{
    				leftOver.insert(mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		set<vector<int>> leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp = {frogs[lo][0], -1};
    				set<vector<int>>::iterator iter = leftOver.upper_bound(temp);
    				vector<vector<int>> temp;
    				for (; iter != leftOver.end(); )
    				{
    					if (segTree.data[lo][0] + segTree.data[lo][1] < (*iter)[0]) break;
    					frogs[lo][1] += (*iter)[1];
    					frogs[lo][3]++;
    					//cout << frogs[lo][1] << endl;
    					segTree.Update(lo, (*iter)[1]);
    					//iter = leftOver.erase(iter);
    					temp.push_back( *iter );
    					++iter;
    				}

    				for (int t = 0; t < temp.size(); ++t)
    					leftOver.erase( temp[t] );
    			}
    			else
    			{
    				leftOver.insert(mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <deque>
#include <bits/stdc++.h>

using namespace std;

class Seg
{
public:

	Seg(vector< vector<int> >& frogs)
	{
		n    = frogs.size();
		p2p  = vector<int>(n, -1);
		data = frogs;
		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

		Build(1, 0, n - 1, -1);
	}

	int Build(int index, int lo, int hi, int parent)
	{
		if (lo > hi) return INT_MIN;
		if (lo == hi)
		{
			st[index][0] = lo;
			st[index][1] = hi;
			st[index][2] = data[lo][0] + data[lo][1];
			st[index][3] = parent;
			p2p[lo]      = index;
			return st[index][2];
		}

		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

		st[index][0] = lo;
		st[index][1] = hi;
		st[index][2] = max(left, right);
		st[index][3] = parent;

		return st[index][2];
	}

	int BinarySearchQuery(int index, int lo, int hi, int val)
	{
		if (st[index][0] == -1 || st[index][1] == -1) return -1;
		if (st[index][1] < lo || st[index][0] > hi) return -1;
		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
		{
			return BinarySearchQuery(index << 1, lo, hi, val);
		}
		else if (st[index << 1 | 1][0] != -1)
		{
			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
		}

		return -1;
	}

	void Update(int pos, int val)
	{
		int index     = p2p[pos];
		int reach     = st[index][2] + val;
		data[pos][1] += val;
		while (index != -1)
		{
			st[index][2] = max(st[index][2], reach);
			index        = st[index][3];
		}
	}

	vector< vector<int> > data;
	vector< vector<int> > st;
	vector< int > p2p;
	int n;
};

class Solution
{
public:

	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
	{
		sort(frogs.begin(), frogs.end());
		Seg segTree(frogs);

		set<vector<int>> leftOver;
		for (int i = 0; i < mos.size(); ++i)
		{
			vector<int> temp = {mos[i][0], -1};
			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
			int pos          = it - frogs.begin();
			if (pos == -1) continue;

			int lo = 0;
			int hi = pos;
			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
			if (ret != -1)
			{
				lo = ret;
				frogs[lo][1] += mos[i][1];
				frogs[lo][3]++;
				segTree.Update(lo, mos[i][1]);

				//Update leftover
				temp = {frogs[lo][0], -1};
				set<vector<int>>::iterator iter = leftOver.upper_bound(temp);
				for (; iter != leftOver.end(); )
				{
					const vector<int>& vec = *iter;
					if (segTree.data[lo][0] + segTree.data[lo][1] < vec[0]) break;
					frogs[lo][1] += vec[1];
					frogs[lo][3]++;
					segTree.Update(lo, vec[1]);
					iter = leftOver.erase(iter);
				}
			}
			else
			{
				leftOver.insert(mos[i]);
			}
		}

		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
		for (int i = 0; i < frogs.size(); ++i)
		{
			res[ frogs[i][2] ][0] = frogs[i][3];
			res[ frogs[i][2] ][1] = frogs[i][1];
		}

		for (int i = 0; i < res.size(); ++i)
		{
			cout << res[i][0] << " " << res[i][1] << endl;
		}
	}

};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > frogs(n, vector<int>(4, 0));
	for (int i = 0; i < n; ++i)
	{
		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
		frogs[i][2] = i;
	}

	vector< vector<int> > mos(m, vector<int>(2, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d", &mos[i][0], &mos[i][1]);
	}

	Solution obj;
	obj.Solve(frogs, mos);
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <deque>
#include <bits/stdc++.h>

using namespace std;

class Seg
{
public:

	Seg(vector< vector<int> >& frogs)
	{
		n    = frogs.size();
		p2p  = vector<int>(n, -1);
		data = frogs;
		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

		Build(1, 0, n - 1, -1);
	}

	int Build(int index, int lo, int hi, int parent)
	{
		if (lo > hi) return INT_MIN;
		if (lo == hi)
		{
			st[index][0] = lo;
			st[index][1] = hi;
			st[index][2] = data[lo][0] + data[lo][1];
			st[index][3] = parent;
			p2p[lo]      = index;
			return st[index][2];
		}

		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

		st[index][0] = lo;
		st[index][1] = hi;
		st[index][2] = max(left, right);
		st[index][3] = parent;

		return st[index][2];
	}

	int BinarySearchQuery(int index, int lo, int hi, int val)
	{
		if (st[index][0] == -1 || st[index][1] == -1) return -1;
		if (st[index][1] < lo || st[index][0] > hi) return -1;
		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
		{
			return BinarySearchQuery(index << 1, lo, hi, val);
		}
		else if (st[index << 1 | 1][0] != -1)
		{
			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
		}

		return -1;
	}

	void Update(int pos, int val)
	{
		int index     = p2p[pos];
		int reach     = st[index][2] + val;
		data[pos][1] += val;
		while (index != -1)
		{
			st[index][2] = max(st[index][2], reach);
			index        = st[index][3];
		}
	}

	vector< vector<int> > data;
	vector< vector<int> > st;
	vector< int > p2p;
	int n;
};

class Solution
{
public:

	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
	{
		sort(frogs.begin(), frogs.end());
		Seg segTree(frogs);

		vector< vector<int> > leftOver;
		for (int i = 0; i < mos.size(); ++i)
		{
			vector<int> temp = {mos[i][0], -1};
			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
			int pos          = it - frogs.begin();
			if (pos == -1) continue;

			int lo = 0;
			int hi = pos;
			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
			if (ret != -1)
			{
				lo = ret;
				frogs[lo][1] += mos[i][1];
				frogs[lo][3]++;
				segTree.Update(lo, mos[i][1]);

				//Update leftover
				temp         = {frogs[lo][0], -1};
				int start    = upper_bound(leftOver.begin(), leftOver.end(), temp) - leftOver.begin();
				int end      = start;
				for (; end < leftOver.size(); ++end)
				{
					if (segTree.data[lo][0] + segTree.data[lo][1] < leftOver[end][0]) break;
					frogs[lo][1] += leftOver[end][1];
					frogs[lo][3]++;
					segTree.Update(lo, leftOver[end][1]);
				}
				int num = end - start;
				if (num != 0) leftOver.erase(leftOver.begin() + start, leftOver.begin() + end);
			}
			else
			{
				auto it = upper_bound(leftOver.begin(), leftOver.end(), mos[i]);
				leftOver.insert(it, mos[i]);
			}
		}

		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
		for (int i = 0; i < frogs.size(); ++i)
		{
			res[ frogs[i][2] ][0] = frogs[i][3];
			res[ frogs[i][2] ][1] = frogs[i][1];
		}

		for (int i = 0; i < res.size(); ++i)
		{
			cout << res[i][0] << " " << res[i][1] << endl;
		}
	}

};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > frogs(n, vector<int>(4, 0));
	for (int i = 0; i < n; ++i)
	{
		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
		frogs[i][2] = i;
	}

	vector< vector<int> > mos(m, vector<int>(2, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d", &mos[i][0], &mos[i][1]);
	}

	Solution obj;
	obj.Solve(frogs, mos);
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <deque>
#include <bits/stdc++.h>

using namespace std;

class Seg
{
public:

	Seg(vector< vector<int> >& frogs)
	{
		n    = frogs.size();
		p2p  = vector<int>(n, -1);
		data = frogs;
		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

		Build(1, 0, n - 1, -1);
	}

	int Build(int index, int lo, int hi, int parent)
	{
		if (lo > hi) return INT_MIN;
		if (lo == hi)
		{
			st[index][0] = lo;
			st[index][1] = hi;
			st[index][2] = data[lo][0] + data[lo][1];
			st[index][3] = parent;
			p2p[lo]      = index;
			return st[index][2];
		}

		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

		st[index][0] = lo;
		st[index][1] = hi;
		st[index][2] = max(left, right);
		st[index][3] = parent;

		return st[index][2];
	}

	int BinarySearchQuery(int index, int lo, int hi, int val)
	{
		if (st[index][0] == -1 || st[index][1] == -1) return -1;
		if (st[index][1] < lo || st[index][0] > hi) return -1;
		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
		{
			return BinarySearchQuery(index << 1, lo, hi, val);
		}
		else if (st[index << 1 | 1][0] != -1)
		{
			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
		}

		return -1;
	}

	void Update(int pos, int val)
	{
		int index     = p2p[pos];
		int reach     = st[index][2] + val;
		data[pos][1] += val;
		while (index != -1)
		{
			st[index][2] = max(st[index][2], reach);
			index        = st[index][3];
		}
	}

	vector< vector<int> > data;
	vector< vector<int> > st;
	vector< int > p2p;
	int n;
};

class Solution
{
public:

	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
	{
		sort(frogs.begin(), frogs.end());
		Seg segTree(frogs);

		set<vector<int>> leftOver;
		for (int i = 0; i < mos.size(); ++i)
		{
			vector<int> temp = {mos[i][0], -1};
			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
			int pos          = it - frogs.begin();
			if (pos == -1) continue;

			int lo = 0;
			int hi = pos;
			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
			if (ret != -1)
			{
				lo = ret;
				frogs[lo][1] += mos[i][1];
				frogs[lo][3]++;
				segTree.Update(lo, mos[i][1]);

				//Update leftover
				temp = {frogs[lo][0], -1};
				set<vector<int>>::iterator iter = leftOver.lower_bound(temp);
				for (; iter != leftOver.end(); )
				{
					const vector<int>& vec = *iter;
					if (segTree.data[lo][0] + segTree.data[lo][1] < vec[0]) break;
					frogs[lo][1] += vec[1];
					frogs[lo][3]++;
					segTree.Update(lo, vec[1]);
					iter = leftOver.erase(iter);
				}
			}
			else
			{
				leftOver.insert(mos[i]);
			}
		}

		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
		for (int i = 0; i < frogs.size(); ++i)
		{
			res[ frogs[i][2] ][0] = frogs[i][3];
			res[ frogs[i][2] ][1] = frogs[i][1];
		}

		for (int i = 0; i < res.size(); ++i)
		{
			cout << res[i][0] << " " << res[i][1] << endl;
		}
	}

};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > frogs(n, vector<int>(4, 0));
	for (int i = 0; i < n; ++i)
	{
		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
		frogs[i][2] = i;
	}

	vector< vector<int> > mos(m, vector<int>(2, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d", &mos[i][0], &mos[i][1]);
	}

	Solution obj;
	obj.Solve(frogs, mos);
}


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		multiset<vector<int>> leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp = {frogs[lo][0], -1};
    				set<vector<int>>::iterator iter = leftOver.upper_bound(temp);
    				vector<vector<int>> temp;
    				for (; iter != leftOver.end(); )
    				{
    					if (segTree.data[lo][0] + segTree.data[lo][1] < (*iter)[0]) break;
    					frogs[lo][1] += (*iter)[1];
    					frogs[lo][3]++;
    					//cout << frogs[lo][1] << endl;
    					segTree.Update(lo, (*iter)[1]);
    					//iter = leftOver.erase(iter);
    					temp.push_back( *iter );
    					++iter;
    				}

    				for (int t = 0; t < temp.size(); ++t)
    					leftOver.erase( temp[t] );
    			}
    			else
    			{
    				leftOver.insert(mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		vector< vector<int> > leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp         = {frogs[lo][0], -1};
    				int start    = upper_bound(leftOver.begin(), leftOver.end(), temp) - leftOver.begin();
    				int end      = start;
    				for (; end < leftOver.size(); ++end)
    				{
    					if (segTree.data[lo][0] + segTree.data[lo][1] < leftOver[end][0]) break;
    					frogs[lo][1] += leftOver[end][1];
    					frogs[lo][3]++;
    					segTree.Update(lo, leftOver[end][1]);
    				}
    				int num = end - start;
    				if (num != 0) leftOver.erase(leftOver.begin() + start, leftOver.begin() + end);
    			}
    			else
    			{
    				auto it = upper_bound(leftOver.begin(), leftOver.end(), mos[i]);
    				leftOver.insert(it, mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <deque>
#include <bits/stdc++.h>

using namespace std;

class Seg
{
public:

	Seg(vector< vector<int> >& frogs)
	{
		n    = frogs.size();
		p2p  = vector<int>(n, -1);
		data = frogs;
		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

		Build(1, 0, n - 1, -1);
	}

	int Build(int index, int lo, int hi, int parent)
	{
		if (lo > hi) return INT_MIN;
		if (lo == hi)
		{
			st[index][0] = lo;
			st[index][1] = hi;
			st[index][2] = data[lo][0] + data[lo][1];
			st[index][3] = parent;
			p2p[lo]      = index;
			return st[index][2];
		}

		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

		st[index][0] = lo;
		st[index][1] = hi;
		st[index][2] = max(left, right);
		st[index][3] = parent;

		return st[index][2];
	}

	int Query(int index, int lo, int hi)
	{
		if (lo > hi) return INT_MIN;
		if (st[index][1] < lo || st[index][0] > hi) return INT_MIN;
		if (st[index][0] >= lo && st[index][1] <= hi) return st[index][2];

		int left = INT_MIN, right = INT_MIN;
		if (st[index][0] != -1 && st[index << 1][1] >= lo)     left = Query(index << 1, lo, hi);
		if (st[index][1] != -1 && st[index << 1 | 1][0] <= hi) right = Query(index << 1 | 1, lo, hi);

		return max(left, right);
	}

	void Update(int pos, int val)
	{
		int index     = p2p[pos];
		int reach     = st[index][2] + val;
		data[pos][1] += val;
		while (index != -1)
		{
			st[index][2] = max(st[index][2], reach);
			index        = st[index][3];
		}
	}

	vector< vector<int> > data;
	vector< vector<int> > st;
	vector< int > p2p;
	int n;
};

class Solution
{
public:

	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
	{
		sort(frogs.begin(), frogs.end());
		Seg segTree(frogs);

		vector< vector<int> > leftOver;
		for (int i = 0; i < mos.size(); ++i)
		{
			vector<int> temp = {mos[i][0], -1};
			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
			int pos          = it - frogs.begin();

			int lo = 0;
			int hi = pos;
			if (FindMatch(segTree, lo, hi, mos[i]) == true)
			{
				frogs[lo][1] += mos[i][1];
				frogs[lo][3]++;
				segTree.Update(lo, mos[i][1]);

				//Update leftover
				temp         = {frogs[lo][0], -1};
				int start    = upper_bound(leftOver.begin(), leftOver.end(), temp) - leftOver.begin();
				int end      = start;
				for (; end < leftOver.size(); ++end)
				{
					if (segTree.data[lo][0] + segTree.data[lo][1] < leftOver[end][0]) break;
					frogs[lo][1] += leftOver[end][1];
					frogs[lo][3]++;
					segTree.Update(lo, leftOver[end][1]);
				}
				int num = end - start;
				if (num != 0) leftOver.erase(leftOver.begin() + start, leftOver.begin() + end);
			}
			else
			{
				auto it = upper_bound(leftOver.begin(), leftOver.end(), mos[i]);
				leftOver.insert(it, mos[i]);
			}
		}

		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
		for (int i = 0; i < frogs.size(); ++i)
		{
			res[ frogs[i][2] ][0] = frogs[i][3];
			res[ frogs[i][2] ][1] = frogs[i][1];
		}

		for (int i = 0; i < res.size(); ++i)
		{
			cout << res[i][0] << " " << res[i][1] << endl;
		}
	}

	bool FindMatch(Seg& segTree, int& lo, int& hi, vector<int>& cur)
	{
		int maxReach = 0;
		while (lo < hi)
		{
			int mid  = lo + (hi - lo) / 2;
			maxReach = segTree.Query(1, 0, mid);

			if (maxReach < cur[0]) lo = mid + 1;
		                      else hi = mid;
		}
		maxReach = segTree.Query(1, 0, lo);

		if (maxReach >= cur[0]) return true;
		                   else return false;
	}
};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > frogs(n, vector<int>(4, 0));
	for (int i = 0; i < n; ++i)
	{
		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
		frogs[i][2] = i;
	}

	vector< vector<int> > mos(m, vector<int>(2, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d", &mos[i][0], &mos[i][1]);
	}

	Solution obj;
	obj.Solve(frogs, mos);
}


#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <deque>
#include <bits/stdc++.h>

using namespace std;

class Seg
{
public:

	Seg(vector< vector<int> >& frogs)
	{
		n    = frogs.size();
		p2p  = vector<int>(n, -1);
		data = frogs;
		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

		Build(1, 0, n - 1, -1);
	}

	int Build(int index, int lo, int hi, int parent)
	{
		if (lo > hi) return INT_MIN;
		if (lo == hi)
		{
			st[index][0] = lo;
			st[index][1] = hi;
			st[index][2] = data[lo][0] + data[lo][1];
			st[index][3] = parent;
			p2p[lo]      = index;
			return st[index][2];
		}

		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

		st[index][0] = lo;
		st[index][1] = hi;
		st[index][2] = max(left, right);
		st[index][3] = parent;

		return st[index][2];
	}

	int Query(int index, int lo, int hi)
	{
		if (lo > hi) return INT_MIN;
		if (st[index][1] < lo || st[index][0] > hi) return INT_MIN;
		if (st[index][0] >= lo && st[index][1] <= hi) return st[index][2];

		int left = INT_MIN, right = INT_MIN;
		if (st[index][0] != -1 && st[index << 1][1] >= lo)     left = Query(index << 1, lo, hi);
		if (st[index][1] != -1 && st[index << 1 | 1][0] <= hi) right = Query(index << 1 | 1, lo, hi);

		return max(left, right);
	}

	void Update(int pos, int val)
	{
		int index     = p2p[pos];
		int reach     = st[index][2] + val;
		data[pos][1] += val;
		while (index != -1)
		{
			st[index][2] = max(st[index][2], reach);
			index        = st[index][3];
		}
	}

	vector< vector<int> > data;
	vector< vector<int> > st;
	vector< int > p2p;
	int n;
};

class Solution
{
public:

	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
	{
		sort(frogs.begin(), frogs.end());
		Seg segTree(frogs);

		vector< vector<int> > leftOver;
		for (int i = 0; i < mos.size(); ++i)
		{
			vector<int> temp = {mos[i][0], -1};
			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
			int pos          = it - frogs.begin();
			if (pos == -1) continue;

			int lo = 0;
			int hi = pos;
			if (FindMatch(segTree, lo, hi, mos[i]) == true)
			{
				frogs[lo][1] += mos[i][1];
				frogs[lo][3]++;
				segTree.Update(lo, mos[i][1]);

				//Update leftover
				temp         = {frogs[lo][0], -1};
				int start    = upper_bound(leftOver.begin(), leftOver.end(), temp) - leftOver.begin();
				int end      = start;
				for (; end < leftOver.size(); ++end)
				{
					if (segTree.data[lo][0] + segTree.data[lo][1] < leftOver[end][0]) break;
					frogs[lo][1] += leftOver[end][1];
					frogs[lo][3]++;
					segTree.Update(lo, leftOver[end][1]);
				}
				int num = end - start;
				if (num != 0) leftOver.erase(leftOver.begin() + start, leftOver.begin() + end);
			}
			else
			{
				auto it = upper_bound(leftOver.begin(), leftOver.end(), mos[i]);
				leftOver.insert(it, mos[i]);
			}
		}

		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
		for (int i = 0; i < frogs.size(); ++i)
		{
			res[ frogs[i][2] ][0] = frogs[i][3];
			res[ frogs[i][2] ][1] = frogs[i][1];
		}

		for (int i = 0; i < res.size(); ++i)
		{
			cout << res[i][0] << " " << res[i][1] << endl;
		}
	}

	bool FindMatch(Seg& segTree, int& lo, int& hi, vector<int>& cur)
	{
		int maxReach = 0;
		while (lo < hi)
		{
			int mid  = lo + (hi - lo) / 2;
			maxReach = segTree.Query(1, 0, mid);

			if (maxReach < cur[0]) lo = mid + 1;
		                      else hi = mid;
		}
		maxReach = segTree.Query(1, 0, lo);

		if (maxReach >= cur[0]) return true;
		                   else return false;
	}
};

int main(int argc, char** argv)
{
	int n, m;
	scanf("%d", &n);
	scanf("%d", &m);

	vector< vector<int> > frogs(n, vector<int>(4, 0));
	for (int i = 0; i < n; ++i)
	{
		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
		frogs[i][2] = i;
	}

	vector< vector<int> > mos(m, vector<int>(2, 0));
	for (int i = 0; i < m; ++i)
	{
		scanf("%d %d", &mos[i][0], &mos[i][1]);
	}

	Solution obj;
	obj.Solve(frogs, mos);
}


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		set<vector<int>> leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp = {frogs[lo][0], -1};
    				set<vector<int>>::iterator iter = leftOver.upper_bound(temp);
    				for (; iter != leftOver.end(); )
    				{
    					if (segTree.data[lo][0] + segTree.data[lo][1] < (*iter)[0]) break;
    					frogs[lo][1] += (*iter)[1];
    					frogs[lo][3]++;
    					segTree.Update(lo, (*iter)[1]);
    					iter = leftOver.erase(iter);
    				}
    			}
    			else
    			{
    				leftOver.insert(mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


    #include <iostream>
    #include <vector>
    #include <set>
    #include <map>
    #include <string>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <deque>
    #include <bits/stdc++.h>

    using namespace std;

    class Seg
    {
    public:

    	Seg(vector< vector<int> >& frogs)
    	{
    		n    = frogs.size();
    		p2p  = vector<int>(n, -1);
    		data = frogs;
    		st   = vector< vector<int> >(n * 4 + 1, vector<int>(4, -1));

    		Build(1, 0, n - 1, -1);
    	}

    	int Build(int index, int lo, int hi, int parent)
    	{
    		if (lo > hi) return INT_MIN;
    		if (lo == hi)
    		{
    			st[index][0] = lo;
    			st[index][1] = hi;
    			st[index][2] = data[lo][0] + data[lo][1];
    			st[index][3] = parent;
    			p2p[lo]      = index;
    			return st[index][2];
    		}

    		int left  = Build(index << 1, lo, lo + (hi - lo) / 2,         index);
    		int right = Build(index << 1 | 1, lo + (hi - lo) / 2 + 1, hi, index);

    		st[index][0] = lo;
    		st[index][1] = hi;
    		st[index][2] = max(left, right);
    		st[index][3] = parent;

    		return st[index][2];
    	}

    	int BinarySearchQuery(int index, int lo, int hi, int val)
    	{
    		if (st[index][0] == -1 || st[index][1] == -1) return -1;
    		if (st[index][1] < lo || st[index][0] > hi) return -1;
    		if (st[index][0] == st[index][1] && st[index][2] >= val) return st[index][0];

    		if (st[index << 1][0] != -1 && st[index << 1][2] >= val)
    		{
    			return BinarySearchQuery(index << 1, lo, hi, val);
    		}
    		else if (st[index << 1 | 1][0] != -1)
    		{
    			return BinarySearchQuery(index << 1 | 1, lo, hi, val);
    		}

    		return -1;
    	}

    	void Update(int pos, int val)
    	{
    		int index     = p2p[pos];
    		int reach     = st[index][2] + val;
    		data[pos][1] += val;
    		while (index != -1)
    		{
    			st[index][2] = max(st[index][2], reach);
    			index        = st[index][3];
    		}
    	}

    	vector< vector<int> > data;
    	vector< vector<int> > st;
    	vector< int > p2p;
    	int n;
    };

    class Solution
    {
    public:

    	void Solve(vector< vector<int> >& frogs, vector< vector<int> >& mos)
    	{
    		sort(frogs.begin(), frogs.end());
    		Seg segTree(frogs);

    		multiset<vector<int>> leftOver;
    		for (int i = 0; i < mos.size(); ++i)
    		{
    			vector<int> temp = {mos[i][0], -1};
    			auto it          = lower_bound(frogs.begin(), frogs.end(), temp);
    			if (it != frogs.end() && (*it)[0] > mos[i][0]) --it;
    			int pos          = it - frogs.begin();
    			if (pos == -1) continue;

    			int lo = 0;
    			int hi = pos;
    			int ret = segTree.BinarySearchQuery(1, lo, hi, mos[i][0]);
    			if (ret != -1)
    			{
    				lo = ret;
    				frogs[lo][1] += mos[i][1];
    				frogs[lo][3]++;
    				segTree.Update(lo, mos[i][1]);

    				//Update leftover
    				temp = {frogs[lo][0], -1};
    				multiset<vector<int>>::iterator iter = leftOver.upper_bound(temp);
    				vector<vector<int>> temp;
    				for (; iter != leftOver.end(); )
    				{
    					if (segTree.data[lo][0] + segTree.data[lo][1] < (*iter)[0]) break;
    					frogs[lo][1] += (*iter)[1];
    					frogs[lo][3]++;
    					//cout << frogs[lo][1] << endl;
    					segTree.Update(lo, (*iter)[1]);
    					iter = leftOver.erase(iter);
    				}
    			}
    			else
    			{
    				leftOver.insert(mos[i]);
    			}
    		}

    		vector< vector<int> > res(frogs.size(), vector<int>(2, 0));
    		for (int i = 0; i < frogs.size(); ++i)
    		{
    			res[ frogs[i][2] ][0] = frogs[i][3];
    			res[ frogs[i][2] ][1] = frogs[i][1];
    		}

    		for (int i = 0; i < res.size(); ++i)
    		{
    			cout << res[i][0] << " " << res[i][1] << endl;
    		}
    	}

    };

    int main(int argc, char** argv)
    {
    	int n, m;
    	scanf("%d", &n);
    	scanf("%d", &m);

    	vector< vector<int> > frogs(n, vector<int>(4, 0));
    	for (int i = 0; i < n; ++i)
    	{
    		scanf("%d %d", &frogs[i][0], &frogs[i][1]);
    		frogs[i][2] = i;
    	}

    	vector< vector<int> > mos(m, vector<int>(2, 0));
    	for (int i = 0; i < m; ++i)
    	{
    		scanf("%d %d", &mos[i][0], &mos[i][1]);
    	}

    	Solution obj;
    	obj.Solve(frogs, mos);
    }


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T,class U> using Pa = pair<T,U>;
template<class T> using vec = vector<T>;
template<class T> using vvec = vector<vec<T>>;

template<typename Monoid,typename OperatorMonoid,typename F,typename G,typename H>
class LazySegmentTree {
private:
	int sz,height;
	vec<Monoid> data;
	vec<OperatorMonoid> lazy;
	const F op;
	const G homo;
	const H comp;
  	const Monoid e;
	const OperatorMonoid Oe;
public:
	LazySegmentTree(int n,const F op,const G homo,const H comp,
					const Monoid &e,const OperatorMonoid Oe)
		: op(op),homo(homo),comp(comp),e(e),Oe(Oe) {
		sz = 1;
		height = 0;
		while(sz<=n) sz <<= 1,height++;
		data.assign(2*sz,e);
		lazy.assign(2*sz,Oe);
	}

	void set(int k,const Monoid &x) {
		data[k+sz] = x;
	}

	void build() {
		for(int k=sz-1;k>0;k--) {
			data[k] = op(data[2*k], data[2*k+1]);
		}
	}

	inline void propagate(int k) {
		if(lazy[k]!=Oe) {
			lazy[2*k] = comp(lazy[2*k], lazy[k]);
			lazy[2*k+1] = comp(lazy[2*k+1], lazy[k]);
			data[k] = reflect(k);
			lazy[k] = Oe;
		}
	}

	inline Monoid reflect(int k) {
		return lazy[k] == Oe? data[k]:homo(data[k],lazy[k]);
	}

	inline void recalc(int k) {
		while(k>>=1) data[k] = op(reflect(2*k), reflect(2*k+1));
	}

	inline void thrust(int k) {
		for(int i=height;i>0;i--) propagate(k>>i);
	}

	void update(int a, int b, const OperatorMonoid &x) {
		thrust(a+=sz);
		thrust(b+=sz-1);
		for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
			if(l&1) lazy[l] = comp(lazy[l],x),++l;
			if(r&1) --r, lazy[r] = comp(lazy[r],x);
		}
		recalc(a);
		recalc(b);
	}

	Monoid query(int a, int b) {
		thrust(a+=sz);
		thrust(b+=sz-1);
		Monoid L = e, R = e;
		for(int l=a, r=b+1;l<r;l>>= 1,r>>=1) {
			if(l&1) L = op(L,reflect(l++));
			if(r&1) R = op(reflect(--r),R);
		}
		return op(L,R);
	}

	Monoid operator[](const int &k) {
		return query(k,k+1);
	}
};

template <class T>
class Compress{
public:
    map<T,int> idx;
    map<int,T> value;
    vector<T> cmp;
    int N;
    Compress(vector<T> v){
        for(auto& x:v) cmp.push_back(x);
        sort(cmp.begin(),cmp.end());
        cmp.erase(unique(cmp.begin(),cmp.end()),cmp.end());
        N = cmp.size();
        for(int i=0;i<N;i++) idx[cmp[i]] = i;
    }
    int id(T val){return idx[val];}
    T val(int id){return cmp[id];}
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N,M;
    cin >> N >> M;
    vec<ll> X(N),T(N),P(M),B(M);
    for(int i=0;i<N;i++) cin >> X[i] >> T[i];
    for(int i=0;i<M;i++) cin >> P[i] >> B[i];
    Compress<ll> cmp(P);
    int m = cmp.N;
    vec<int> idx(N);
    iota(idx.begin(),idx.end(),0);
    sort(idx.begin(),idx.end(),[&](int i,int j){return X[i]<X[j];});
    const ll inf = 1e18;

    auto op1 = [](ll a,ll b){return min(a,b);};
    auto homo1 = [](ll a,ll b){return b!=inf? b:a;};
    auto comp1 = homo1;

	struct mosq{
		ll cnt,size;
		bool operator==(const mosq& r)const{
			return cnt==r.cnt && size==r.size;
		}
		bool operator!=(const mosq& r)const{
			return cnt!=r.cnt || size!=r.size;
		}
	};

	mosq e = {0,0};

    auto op2 = [](mosq a,mosq b){return (mosq){a.cnt+b.cnt,a.size+b.size};};
    auto homo2 = [](mosq a,mosq b){return b.cnt!=inf? b:a;};
    auto comp2 = homo2;

    LazySegmentTree<ll,ll,decltype(op1),decltype(homo1),decltype(comp1)>
    flog(m,op1,homo1,comp1,inf,inf);
    LazySegmentTree<mosq,mosq,decltype(op2),decltype(homo2),decltype(comp2)>
    mosqs(m,op2,homo2,comp2,e,{inf,inf});

    int a = 0;
    for(auto i:idx){
		while(a<m && cmp.val(a)<X[i]) a++;
        while(a<m && cmp.val(a)<=X[i]+T[i]){
            flog.set(a,i);
            a++;
        }
    }
    flog.build();
	vec<ll> ans(N);
    vec<ll> W = cmp.cmp;
    for(int q=0;q<M;q++){
        ll p = P[q],b = B[q];
        mosq now = mosqs[cmp.id(p)];
        mosqs.update(cmp.id(p),cmp.id(p)+1,(mosq){now.cnt+1,now.size+b});
        ll id = flog[cmp.id(p)];
		if(id==inf) continue;
        while(true){
			ll r = upper_bound(W.begin(),W.end(),X[id]+T[id])-W.begin();
			ll l = cmp.id(p);
			flog.update(l,r,id);
			mosq sum = mosqs.query(l,r);
			if(sum.cnt==0) break;
			ans[id] += sum.cnt;
			T[id] += sum.size;
			mosqs.update(l,r,e);
		}
    }
	for(int i=0;i<N;i++) cout << ans[i] << " " << T[i] << "\n";
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T,class U> using Pa = pair<T,U>;
template<class T> using vec = vector<T>;
template<class T> using vvec = vector<vec<T>>;

template<typename Monoid,typename OperatorMonoid,typename F,typename G,typename H>
class LazySegmentTree {
private:
	int sz,height;
	vec<Monoid> data;
	vec<OperatorMonoid> lazy;
	const F op;
	const G homo;
	const H comp;
  	const Monoid e;
	const OperatorMonoid Oe;
public:
	LazySegmentTree(int n,const F op,const G homo,const H comp,
					const Monoid &e,const OperatorMonoid Oe)
		: op(op),homo(homo),comp(comp),e(e),Oe(Oe) {
		sz = 1;
		height = 0;
		while(sz<=n) sz <<= 1,height++;
		data.assign(2*sz,e);
		lazy.assign(2*sz,Oe);
	}

	void set(int k,const Monoid &x) {
		data[k+sz] = x;
	}

	void build() {
		for(int k=sz-1;k>0;k--) {
			data[k] = op(data[2*k], data[2*k+1]);
		}
	}

	inline void propagate(int k) {
		if(lazy[k]!=Oe) {
			lazy[2*k] = comp(lazy[2*k], lazy[k]);
			lazy[2*k+1] = comp(lazy[2*k+1], lazy[k]);
			data[k] = reflect(k);
			lazy[k] = Oe;
		}
	}

	inline Monoid reflect(int k) {
		return lazy[k] == Oe? data[k]:homo(data[k],lazy[k]);
	}

	inline void recalc(int k) {
		while(k>>=1) data[k] = op(reflect(2*k), reflect(2*k+1));
	}

	inline void thrust(int k) {
		for(int i=height;i>0;i--) propagate(k>>i);
	}

	void update(int a, int b, const OperatorMonoid &x) {
		thrust(a+=sz);
		thrust(b+=sz-1);
		for(int l=a,r=b+1;l<r;l>>=1,r>>=1) {
			if(l&1) lazy[l] = comp(lazy[l],x),++l;
			if(r&1) --r, lazy[r] = comp(lazy[r],x);
		}
		recalc(a);
		recalc(b);
	}

	Monoid query(int a, int b) {
		thrust(a+=sz);
		thrust(b+=sz-1);
		Monoid L = e, R = e;
		for(int l=a, r=b+1;l<r;l>>= 1,r>>=1) {
			if(l&1) L = op(L,reflect(l++));
			if(r&1) R = op(reflect(--r),R);
		}
		return op(L,R);
	}

	Monoid operator[](const int &k) {
		return query(k,k+1);
	}
};

template <class T>
class Compress{
public:
    map<T,int> idx;
    map<int,T> value;
    vector<T> cmp;
    int N;
    Compress(vector<T> v){
        for(auto& x:v) cmp.push_back(x);
        sort(cmp.begin(),cmp.end());
        cmp.erase(unique(cmp.begin(),cmp.end()),cmp.end());
        N = cmp.size();
        for(int i=0;i<N;i++) idx[cmp[i]] = i;
    }
    int id(T val){return idx[val];}
    T val(int id){return cmp[id];}
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N,M;
    cin >> N >> M;
    vec<ll> X(N),T(N),P(M),B(M);
    for(int i=0;i<N;i++) cin >> X[i] >> T[i];
    for(int i=0;i<M;i++) cin >> P[i] >> B[i];
    Compress<ll> cmp(P);
    int m = cmp.N;
    vec<int> idx(N);
    iota(idx.begin(),idx.end(),0);
    sort(idx.begin(),idx.end(),[&](int i,int j){return X[i]<X[j];});
    const ll inf = 1e18;

    auto op1 = [](ll a,ll b){return min(a,b);};
    auto homo1 = [](ll a,ll b){return b!=inf? b:a;};
    auto comp1 = homo1;

	struct mosq{
		ll cnt,size;
		bool operator==(const mosq& r)const{
			return cnt==r.cnt && size==r.size;
		}
		bool operator!=(const mosq& r)const{
			return cnt!=r.cnt || size!=r.size;
		}
	};

	mosq e = {0,0};

    auto op2 = [](mosq a,mosq b){return (mosq){a.cnt+b.cnt,a.size+b.size};};
    auto homo2 = [](mosq a,mosq b){return b.cnt!=inf? b:a;};
    auto comp2 = homo2;

    LazySegmentTree<ll,ll,decltype(op1),decltype(homo1),decltype(comp1)>
    flog(m,op1,homo1,comp1,inf,inf);
    LazySegmentTree<mosq,mosq,decltype(op2),decltype(homo2),decltype(comp2)>
    mosqs(m,op2,homo2,comp2,e,{inf,inf});

    int a = 0;
    for(auto i:idx){
		while(a<m && cmp.val(a)<X[i]) a++;
        while(a<m && cmp.val(a)<=X[i]+T[i]){
            flog.set(a,i);
            a++;
        }
    }
    flog.build();
//    for(int i=0;i<m;i++) cerr << flog[i] << (i!=m-1? " ":"\n");
	vec<ll> ans(N);
    vec<ll> W = cmp.cmp;
    for(int q=0;q<M;q++){
        ll p = P[q],b = B[q];
        mosq now = mosqs[cmp.id(p)];
        mosqs.update(cmp.id(p),cmp.id(p)+1,(mosq){now.cnt+1,now.size+b});
        ll id = flog[cmp.id(p)];
		if(id==inf) continue;
        while(true){
			ll r = upper_bound(W.begin(),W.end(),X[id]+T[id])-W.begin();
			ll l = lower_bound(W.begin(),W.end(),X[id])-W.begin();
			flog.update(l,r,id);
			mosq sum = mosqs.query(l,r);
			if(sum.cnt==0) break;
			ans[id] += sum.cnt;
			T[id] += sum.size;
			mosqs.update(l,r,e);
		}
    }
	for(int i=0;i<N;i++) cout << ans[i] << " " << T[i] << "\n";
}


#include <bits/stdc++.h>
#define F first
#define S second
typedef long long ll;
using namespace std;

ll n;
ll q;
pair<pair<ll,ll>,ll>  f[100010];

set<pair<ll,ll> > rem;

ll ST[500010];

void build (ll l,ll r,ll nod){
    if (l==r){
        ST[nod]=f[l].F.F+f[l].F.S;
        return;
    }
    ll mid =(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}

ll fnd (ll x,ll l,ll r,ll nod){
    //cout <<l<<" "<<r<<endl;
    if (l==r){
        if (ST[nod]>=x)
            return l;
        return -1;
    }
    ll mid=(l+r)/2;
    if (ST[nod*2]>=x){
        return fnd(x,l,mid,nod*2);
    }else {
        return fnd(x,mid+1,r,nod*2+1);
    }
}
void update(ll idx,ll val,ll l,ll r,ll nod){

    if (l==idx&&r==idx){
        ST[nod]+=val;
        return;
    }
    if (l>idx||r<idx)return;
    ll mid=(l+r)/2;
    update(idx,val,l,mid,nod*2);
    update(idx,val,mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}
pair<ll,ll> ans[100010];
ll res[100010];
int main()
{

    cin >>n;
    cin >>q;
    for (ll i=0;i<n;i++){
        cin >>f[i].F.F>>f[i].F.S;
        f[i].S=i;
    }
    sort(f,f+n);

    build (0,n-1,1);
    for (ll i=0;i<q;i++){
        //cout <<"------------\n";

        ll a,b;
        cin >>a>>b;
        ll z=fnd(a,0,n-1,1);

//        cout <<z<<endl;
        if (f[z].F.F>a)z=-1;
        if (z==-1){
            rem.insert({a,b});
            continue;
        }
        res[f[z].S]++;
        f[z].F.S+=b;
        update(z,b,0,n-1,1);
        auto it=rem.lower_bound({f[z].F.F,0});
        while (rem.size()){
            if (it==rem.end())break;
            if ((*it).F<=f[z].F.F+f[z].F.S){
                res[f[z].S]++;
                f[z].F.S+=(*it).S;
                update(z,(*it).S,0,n-1,1);
                rem.erase(it++);
                continue;
            }
            break;
        }
    }
    for (ll i=0;i<n;i++){
        ans[f[i].S]=f[i].F;
    }
    for (ll i=0;i<n;i++){
        cout <<res[i]<<" "<<ans[i].S<<endl;
    }
    return 0;
}


#include <bits/stdc++.h>
#define F first
#define S second
typedef long long ll;
using namespace std;

ll n;
ll q;
pair<pair<ll,ll>,ll>  f[100010];

set<pair<ll,ll> > rem;

ll ST[500010];

void build (ll l,ll r,ll nod){
    if (l==r){
        ST[nod]=f[l].F.F+f[l].F.S;
        return;
    }
    ll mid =(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}

ll fnd (ll x,ll l,ll r,ll nod){
    //cout <<l<<" "<<r<<endl;
    if (l==r){
        if (ST[nod]>=x)
            return l;
        return -1;
    }
    ll mid=(l+r)/2;
    if (ST[nod*2]>=x){
        return fnd(x,l,mid,nod*2);
    }else if (ST[nod*2+1]>=x){
        return fnd(x,mid+1,r,nod*2+1);
    }else return -1;
}
void update(ll idx,ll val,ll l,ll r,ll nod){

    if (l==idx&&r==idx){
        ST[nod]+=val;
        return;
    }
    if (l>idx||r<idx)return;
    ll mid=(l+r)/2;
    update(idx,val,l,mid,nod*2);
    update(idx,val,mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}
pair<ll,ll> ans[100010];
ll res[100010];
int main()
{

    cin >>n;
    cin >>q;
    for (ll i=0;i<n;i++){
        cin >>f[i].F.F>>f[i].F.S;
        f[i].S=i;
    }
    sort(f,f+n);

    build (0,n-1,1);
    for (ll i=0;i<q;i++){
        //cout <<"------------\n";

        ll a,b;
        cin >>a>>b;
        ll z=fnd(a,0,n-1,1);

//        cout <<z<<endl;
        if (f[z].F.F>a)z=-1;
        if (z==-1){
            rem.insert({a,b});
            continue;
        }
        res[f[z].S]++;
        f[z].F.S+=b;
        update(z,b,0,n-1,1);
        while (rem.size()){
            pair<ll,ll> k=*rem.begin();
            if (k.F<=f[z].F.F+f[z].F.S){
                res[f[z].S]++;
                f[z].F.S+=k.S;
                update(z,k.S,0,n-1,1);
                rem.erase(rem.begin()++);
                continue;
            }
            break;
        }
    }
    for (ll i=0;i<n;i++){
        ans[f[i].S]=f[i].F;
    }
    for (ll i=0;i<n;i++){
        cout <<res[i]<<" "<<ans[i].S<<endl;
    }
    return 0;
}


#include <bits/stdc++.h>
#define F first
#define S second
typedef long long ll;
using namespace std;

ll n;
ll q;
pair<pair<ll,ll>,ll>  f[200010];

multiset<pair<ll,ll> > rem;

ll ST[1000010];

void build (ll l,ll r,ll nod){
    if (l==r){
        ST[nod]= f[l].F.F + f[l].F.S;
        return;
    }
    ll mid =(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}

ll fnd (ll x,ll l,ll r,ll nod){
    //cout <<l<<" "<<r<<endl;
    if (l==r){
        if (ST[nod]>=x)
            return l;
        return -1;
    }
    ll mid=(l+r)/2;
    if (ST[nod*2]>=x){
        return fnd(x,l,mid,nod*2);
    }else {
        return fnd(x,mid+1,r,nod*2+1);
    }
}
void update(ll idx,ll val,ll l,ll r,ll nod){
    if (l==idx&&r==idx){
        ST[nod]+=val;
        return;
    }
    if (l>idx||r<idx)return;
    ll mid=(l+r)/2;
    update(idx,val,l,mid,nod*2);
    update(idx,val,mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}
pair<ll,ll> ans[200010];
ll res[200010];
int main()
{

    cin >>n;
    cin >>q;
    for (ll i=0;i<n;i++){
        cin >>f[i].F.F>>f[i].F.S;
        f[i].S=i;
    }
    sort(f,f+n);

    build (0,n-1,1);
    for (ll i=0;i<q;i++){

        ll a,b;
        cin >>a>>b;
        ll z=fnd(a,0,n-1,1);

//        cout <<z<<endl;
        if (z!=-1&&f[z].F.F>a)z=-1;
        if (z==-1){
            rem.insert({a,b});
            continue;
        }
        res[f[z].S]++;
        f[z].F.S+=b;
        update(z,b,0,n-1,1);
        auto it=rem.lower_bound({f[z].F.F,-1});
        while (rem.size()){
            if (it==rem.end())break;
            if ((*it).F<= f[z].F.F + f[z].F.S){
                res[f[z].S]++;
                f[z].F.S+=(*it).S;
                update(z,(*it).S,0,n-1,1);
                rem.erase(it++);
                continue;
            }
            break;
        }
    }
    for (ll i=0;i<n;i++){
        ans[f[i].S]=f[i].F;
    }
    for (ll i=0;i<n;i++){
        cout <<res[i]<<" "<<ans[i].S<<endl;
    }
    return 0;
}


#include <bits/stdc++.h>
#define F first
#define S second
typedef long long ll;
using namespace std;

ll n;
ll q;
pair<pair<ll,ll>,ll>  f[100010];

set<pair<ll,ll> > rem;

ll ST[500010];

void build (ll l,ll r,ll nod){
    if (l==r){
        ST[nod]=f[l].F.F+f[l].F.S;
        return;
    }
    ll mid =(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}

ll fnd (ll x,ll l,ll r,ll nod){
    //cout <<l<<" "<<r<<endl;
    if (l==r){
        if (ST[nod]>=x)
            return l;
        return -1;
    }
    ll mid=(l+r)/2;
    if (ST[nod*2]>=x){
        return fnd(x,l,mid,nod*2);
    }else {
        return fnd(x,mid+1,r,nod*2+1);
    }
}
void update(ll idx,ll val,ll l,ll r,ll nod){

    if (l==idx&&r==idx){
        ST[nod]+=val;
        return;
    }
    if (l>idx||r<idx)return;
    ll mid=(l+r)/2;
    update(idx,val,l,mid,nod*2);
    update(idx,val,mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}
pair<ll,ll> ans[100010];
ll res[100010];
int main()
{

    cin >>n;
    cin >>q;
    for (ll i=0;i<n;i++){
        cin >>f[i].F.F>>f[i].F.S;
        f[i].S=i;
    }
    sort(f,f+n);

    build (0,n-1,1);
    for (ll i=0;i<q;i++){
        //cout <<"------------\n";

        ll a,b;
        cin >>a>>b;
        ll z=fnd(a,0,n-1,1);

//        cout <<z<<endl;
        if (z!=-1&&f[z].F.F>a)z=-1;
        if (z==-1){
            rem.insert({a,b});
            continue;
        }
        res[f[z].S]++;
        f[z].F.S+=b;
        update(z,b,0,n-1,1);
        auto it=rem.lower_bound({f[z].F.F,0});
        while (rem.size()){
            if (it==rem.end())break;
            if ((*it).F<=f[z].F.F+f[z].F.S){
                res[f[z].S]++;
                f[z].F.S+=(*it).S;
                update(z,(*it).S,0,n-1,1);
                rem.erase(it++);
                continue;
            }
            break;
        }
    }
    for (ll i=0;i<n;i++){
        ans[f[i].S]=f[i].F;
    }
    for (ll i=0;i<n;i++){
        cout <<res[i]<<" "<<ans[i].S<<endl;
    }
    return 0;
}


#include <bits/stdc++.h>
#define F first
#define S second
typedef long long ll;
using namespace std;

ll n;
ll q;
pair<pair<ll,ll>,ll>  f[100010];

set<pair<ll,ll> > rem;

ll ST[500010];

void build (ll l,ll r,ll nod){
    if (l==r){
        ST[nod]=f[l].F.F+f[l].F.S;
        return;
    }
    ll mid =(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}

ll fnd (ll x,ll l,ll r,ll nod){
    //cout <<l<<" "<<r<<endl;
    if (l==r){
        if (ST[nod]>=x)
            return l;
        return -1;
    }
    ll mid=(l+r)/2;
    if (ST[nod*2]>=x){
        return fnd(x,l,mid,nod*2);
    }else if (ST[nod*2+1]>=x){
        return fnd(x,mid+1,r,nod*2+1);
    }else return -1;
}
void update(ll idx,ll val,ll l,ll r,ll nod){

    if (l==idx&&r==idx){
        ST[nod]+=val;
        return;
    }
    if (l>idx||r<idx)return;
    ll mid=(l+r)/2;
    update(idx,val,l,mid,nod*2);
    update(idx,val,mid+1,r,nod*2+1);
    ST[nod]=max(ST[nod*2],ST[nod*2+1]);
}
pair<ll,ll> ans[100010];
ll res[100010];
int main()
{

    cin >>n;
    cin >>q;
    for (ll i=0;i<n;i++){
        cin >>f[i].F.F>>f[i].F.S;
        f[i].S=i;
    }
    sort(f,f+n);

    build (0,n-1,1);
    for (ll i=0;i<q;i++){
        //cout <<"------------\n";

        ll a,b;
        cin >>a>>b;
        ll\ z=fnd(a,0,n-1,1);

//        cout <<z<<endl;
        if (f[z].F.F>a)z=-1;
        if (z==-1){
            rem.insert({a,b});
            continue;
        }
        res[f[z].S]++;
        f[z].F.S+=b;
        update(z,b,0,n-1,1);
        while (rem.size()){
            pair<ll,ll> k=*rem.begin();
            if (k.F<=f[z].F.F+f[z].F.S){
                res[f[z].S]++;
                f[z].F.S+=k.S;
                update(z,k.S,0,n-1,1);
                rem.erase(rem.begin()++);
                continue;
            }
            break;
        }
    }
    for (ll i=0;i<n;i++){
        ans[f[i].S]=f[i].F;
    }
    for (ll i=0;i<n;i++){
        cout <<res[i]<<" "<<ans[i].S<<endl;
    }
    return 0;
}