#include <iostream>
#include<stdio.h>
#include <cstdlib>
using namespace std;
int main()
{
    int maxind2;
    int x[20000];
    int y[20000];
    int z[20000];
    int n,m;
    int index[200];
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>x[i];
    }
    cin>>m;
    for(int i=0;i<m;i++)
    {
        cin>>y[i];
    }
    for(int i=0;i<m;i++)
    {
        cin>>z[i];
    }
int maxind=0;
int num1=0;
int num2=0;
int test=0;
int knew;
int k=0;
int j;
for(int i=0;i<n;i++)
{
for(j=0;j<m;j++)
    if(x[i]==y[j])
    {
        num1++;
    }
    if(num1>0&&num1>num2)
    {
        maxind=j;
        num2=num1;
    }
    if(num1==num2&&num2!=0)
    {test=1; index[k]=j; k++;}
    num1=0;
    knew=k;
}
 num1=0;
 k=0;
if(num2==0)
{
for(int i=0;i<n;i++)
{
for(j=0;j<m;j++)
    if(x[i]==z[j])
    {
        num1++;
    }
    if(num1>0&&num1>num2)
    {
        maxind=j;
        num2=num1;
    }

}
cout<<maxind;
exit(1);
}
num2=0;
if(test)
{
while(knew>k)
{
for(j=0;j<m;j++)
if(x[index[k]]==z[j])
    {
        num1++;
    }
    if(num1>num2)
    {
        maxind2=index[k];
        num2=num1;
    }
k++;
}
cout<<maxind2+1;
exit(1);
}
else {cout<<maxind;}
}


#include <iostream>
#include <unordered_map>

using namespace::std;

int b[200001];
int c[200001];
unordered_map<int, int> mymap;

int main(int argc, char **argv)
{
    memset(b, 0, sizeof(b));
    memset(c, 0, sizeof(c));
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int tmp;
        cin >> tmp;
        if (mymap.find(tmp) != mymap.end()) {
            mymap.find(tmp)->second++;
        } else {
            mymap.insert(make_pair(tmp, 1));
        }
    }
    int m;
    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> b[i];
    }
    for (int i = 0; i < m; i++) {
        cin >> c[i];
    }
    int maxi = 0;
    int maxi2 = 0;
    int pos = -1;
    for (int i = 0; i < m; i++) {
        if (mymap.find(b[i]) != mymap.end()) {
            if (mymap.find(b[i])->second > maxi) {
                maxi = mymap.find(b[i])->second;
                pos = i+1;
                maxi2 = mymap.find(c[i])!=mymap.end() ? mymap.find(c[i])->second : 0;
            } else if (mymap.find(b[i])->second == maxi) {
                if (mymap.find(c[i])!=mymap.end() && mymap.find(c[i])->second > maxi2) {
                    pos = i+1;
                    maxi2 = mymap.find(c[i])->second;
                }
            }
        }
    }
    cout << pos;
    return(0);
}


#include <iostream>
#include <unordered_map>

using namespace::std;

int b[200001];
int c[200001];
unordered_map<int, int> mymap;

int main(int argc, char **argv)
{
    memset(b, 0, sizeof(b));
    memset(c, 0, sizeof(c));
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int tmp;
        cin >> tmp;
        if (mymap.find(tmp) != mymap.end()) {
            mymap.find(tmp)->second++;
        } else {
            mymap.insert(make_pair(tmp, 1));
        }
    }
    int m;
    cin >> m;
    for (int i = 0; i < m; i++) {
        cin >> b[i];
    }
    for (int i = 0; i < m; i++) {
        cin >> c[i];
    }
    int maxi = 0;
    int maxi2 = 0;
    int pos = 1;
    for (int i = 0; i < m; i++) {
        if (mymap.find(b[i]) != mymap.end()) {
            if (mymap.find(b[i])->second > maxi) {
                maxi = mymap.find(b[i])->second;
                pos = i+1;
                maxi2 = mymap.find(c[i])!=mymap.end() ? mymap.find(c[i])->second : 0;
            }
            if (mymap.find(b[i])->second == maxi) {
                if (mymap.find(c[i])!=mymap.end() && mymap.find(c[i])->second > maxi2) {
                    pos = i+1;
                    maxi2 = mymap.find(c[i])->second;
                }
            }
        } else if (maxi == 0 && mymap.find(c[i])!=mymap.end()) {
            if (mymap.find(c[i])->second > maxi2) {
                pos = i+1;
                maxi = mymap.find(c[i])->second;
            }
        }
    }
    cout << pos;
    return(0);
}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        boolean[] s1 = new boolean[5001];
        boolean[] s2 = new boolean[5001];
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
            s1[s.get(s.size() - 1)] = true;
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        boolean[] used = new boolean[5000];

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;
            s2[f] = true;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                used[l] = true;
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            if (i > -1 && !used[i]) {
                continue;
            }
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                //if (!s1[j] && !s2[j]) {
                //    continue;
                //}
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = r + mixed;
                        count *= mult;
                        if (count > 1000000007) {
                            count %= 1000000007;
                        }
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = l * mixed + r * mixed + mixed * (mixed - 1);
                    count *= mult;
                } else {
                    result += 1;
                    int mult = l + r + mixed * 2;
                    count *= mult;
                }
                if (count > 1000000007) {
                    count %= 1000000007;
                }
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        boolean[] used = new boolean[5000];

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                used[l] = true;
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            if (i > -1 && !used[i]) {
                continue;
            }
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = (r + mixed) % 1000000007;
                        count *= mult;
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = (l * mixed + r * mixed + mixed * (mixed - 1)) % 1000000007;
                    count *= mult;
                } else {
                    result += 1;
                    int mult = (l + r + mixed * 2) % 1000000007;
                    count *= mult;
                }
                count %= 1000000007;
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = (r + mixed) % 1000000007;
                        count *= mult;
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = (l * mixed + r * mixed + mixed * (mixed - 1) / 2) % 1000000007;
                    count *= mult;
                } else {
                    result += 1;
                    int mult = (l + r + mixed * 2) % 1000000007;
                    count *= mult;
                }
                count %= 1000000007;
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        boolean[] s1 = new boolean[5001];
        boolean[] s2 = new boolean[5001];
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
            s1[s.get(s.size() - 1)] = true;
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        boolean[] used = new boolean[5000];

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;
            s2[f] = true;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                used[l] = true;
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            if (i > -1 && !used[i]) {
                continue;
            }
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                if (!s1[j] && !s2[j]) {
                    continue;
                }
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = r + mixed;
                        count *= mult;
                        if (count > 1000000007) {
                            count %= 1000000007;
                        }
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = l * mixed + r * mixed + mixed * (mixed - 1);
                    count *= mult;
                } else {
                    result += 1;
                    int mult = l + r + mixed * 2;
                    count *= mult;
                }
                if (count > 1000000007) {
                    count %= 1000000007;
                }
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = (r + mixed) % 1000000007;
                        count *= mult;
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = (l * mixed + r * mixed + mixed * (mixed - 1)) % 1000000007;
                    count *= mult;
                } else {
                    result += 1;
                    int mult = (l + r + mixed * 2) % 1000000007;
                    count *= mult;
                }
                count %= 1000000007;
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.stream.IntStream;

public class Main {

    static {
        Locale.setDefault(Locale.ENGLISH);
    }

    private static DecimalFormat decimalFormat = new DecimalFormat("#0.00000000");

    private static class Reader implements Closeable {

        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public Reader() {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }

        public Reader(String fileName) {
            try {
                reader = new BufferedReader(new FileReader(fileName));
            } catch (FileNotFoundException e) {
                throw new IllegalStateException("There is no file with given name");
            }
        }

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    String nextLine = reader.readLine();
                    if (nextLine == null) {
                        return null;
                    }
                    tokenizer = new StringTokenizer(nextLine);
                } catch (IOException e) {
                    throw new IllegalStateException("I/O Error");
                }
            }
            return tokenizer.nextToken();
        }

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

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

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

        @Override
        public void close() throws IOException {
            reader.close();
        }
    }

    private static class Pair implements Comparable<Pair> {

        private int x;
        private int y;

        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public int compareTo(Pair o) {
            if (this.x != o.x) return Integer.compare(this.x, o.x);
            return Integer.compare(this.y, o.y);
        }
    }

    private <T> ArrayList<T> createArrayList(int n, T value) {
        ArrayList<T> result = new ArrayList<>();
        IntStream.range(0, n).forEach(i -> result.add(value));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        //Reader reader = new Reader("input.txt");
        PrintWriter writer = new PrintWriter(System.out);
        new Main().solve(reader, writer);
        reader.close();
        writer.close();
    }

    private static class Cow {

        private int l;
        private int r;

        public Cow(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public int getL() {
            return l;
        }

        public int getR() {
            return r;
        }

    }

    private void solve(Reader reader, PrintWriter writer) {
        int n = reader.nextInt();
        int m = reader.nextInt();
        ArrayList<Integer> s = new ArrayList<>();
        boolean[] s1 = new boolean[5001];
        boolean[] s2 = new boolean[5001];
        for (int i = 0; i < n; ++i) {
            s.add(reader.nextInt());
            s1[s.get(s.size() - 1)] = true;
        }

        ArrayList<Cow>[] cowsByF = new ArrayList[5001];
        for (int i = 1; i <= n; ++i) {
            cowsByF[i] = new ArrayList<>();
        }

        boolean[] used = new boolean[5000];

        for (int i = 0; i < m; ++i) {
            int f = reader.nextInt();
            int h = reader.nextInt();
            int l = -1;
            int r = -1;
            s2[f] = true;

            int counter = 0;
            for (int j = 0; j < n; ++j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        l = j;
                        break;
                    }
                }
            }

            counter = 0;
            for (int j = n - 1; j >= 0; --j) {
                if (s.get(j) == f) {
                    counter++;
                    if (counter == h) {
                        r = j;
                        break;
                    }
                }
            }

            if (l != -1) {
                used[l] = true;
                cowsByF[f].add(new Cow(l, r));
            }
        }

        int bestResult = 0;
        long bestCount = 0;

        for (int i = -1; i < n; ++i) { //граница разделения
            if (i > -1 && !used[i]) {
                continue;
            }
            int result = 0;
            long count = 1;
            boolean usedProperCow = false;
            for (int j = 1; j <= n; ++j) { //уровень сладости
                if (!s1[j] && !s2[j]) {
                    continue;
                }
                boolean usedProperCowAtJ = false;
                int l = 0;
                int r = 0;
                int mixed = 0;
                for (Cow cow : cowsByF[j]) {
                    if (cow.l == i) {
                        usedProperCow = true;
                        usedProperCowAtJ = true;
                        continue;
                    }
                    if (cow.l <= i && cow.r <= i) {
                        l++;
                    }
                    if (cow.l > i && cow.r > i) {
                        r++;
                    }
                    if (cow.l <= i && cow.r > i) {
                        mixed++;
                    }
                }
                if (usedProperCowAtJ) {
                    if (r + mixed == 0) {
                        result += 1;
                        continue;
                    } else {
                        result += 2;
                        int mult = (r + mixed) % 1000000007;
                        count *= mult;
                        continue;
                    }
                }
                if (l + r + mixed == 0) {
                    continue;
                }
                if (mixed + (l > 0 ? 1 : 0) + (r > 0 ? 1 : 0) > 1) {
                    result += 2;
                    int mult = (l * mixed + r * mixed + mixed * (mixed - 1)) % 1000000007;
                    count *= mult;
                } else {
                    result += 1;
                    int mult = (l + r + mixed * 2) % 1000000007;
                    count *= mult;
                }
                count %= 1000000007;
            }
            if (result > bestResult) {
                bestResult = result;
                bestCount = count;
            } else if (result == bestResult && (i == -1 || usedProperCow)) {
                bestCount += count;
                bestCount %= 1000000007;
            }
        }
        writer.println(bestResult + " " + bestCount);
    }

}


import java.io.*;
import java.util.*;

public class CF1307E extends PrintWriter {
	CF1307E() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1307E o = new CF1307E(); o.main(); o.flush();
	}

	static final int MD = 1000000007;
	int cnt_; long sum;
	int n, m;
	int[] ss, ii, jj;
	int[] ll, rr, lr, w2;
	void update(int h, int x) {
		Arrays.fill(ll, 0); Arrays.fill(rr, 0); Arrays.fill(lr, 0);
		for (int h_ = 0; h_ < m; h_++) {
			if (h_ == h)
				continue;
			int s_ = ss[h_], i_ = ii[h_], j_ = jj[h_];
			if (i_ < x)
				ll[s_]++;
			if (j_ > x)
				rr[s_]++;
			if (i_ < x && j_ > x)
				lr[s_]++;
		}
		int cnt; long ways;
		if (h == -1) {
			cnt = 0;
			ways = 1;
			for (int s = 0; s < n; s++)
				if (rr[s] > 0) {
					cnt++;
					ways = ways * rr[s] % MD;
				}
		} else {
			Arrays.fill(w2, 0);
			int s = ss[h];
			for (int h_ = 0; h_ < m; h_++) {
				int s_ = ss[h_];
				if (s_ == s)
					continue;
				int i_ = ii[h_], j_ = jj[h_];
				if (i_ < x) {
					int r = rr[s_];
					if (j_ > x)
						r--;
					if (r > 0)
						w2[s_] += r;
				}
			}
			cnt = rr[s] == 0 ? 1 : 2;
			ways = rr[s] == 0 ? 1 : rr[s];
			for (int s_ = 0; s_ < n; s_++) {
				if (s_ == s)
					continue;
				if (w2[s_] > 0) {
					cnt += 2;
					ways = ways * w2[s_] % MD;
				} else if (ll[s_] + rr[s_] - lr[s_] > 0) {
					cnt++;
					ways = ways * (ll[s_] + rr[s_]) % MD;
				}
			}
		}
		if (cnt_ < cnt) {
			cnt_ = cnt;
			sum = ways;
		} else if (cnt_ == cnt)
			sum += ways;
	}
	void main() {
		n = sc.nextInt();
		m = sc.nextInt();
		int[] ss_ = new int[n];
		for (int i = 0; i < n; i++)
			ss_[i] = sc.nextInt() - 1;
		ss = new int[m]; ii = new int[m]; jj = new int[m];
		for (int h = 0; h < m; h++) {
			int s = sc.nextInt() - 1;
			int k = sc.nextInt();
			int i, j, a;
			for (i = 0, a = 0; i < n; i++)
				if (ss_[i] == s && ++a == k)
					break;
			for (j = n - 1, a = 0; j >= 0; j--)
				if (ss_[j] == s && ++a == k)
					break;
			ss[h] = s; ii[h] = i; jj[h] = j;
		}
		ll = new int[n]; rr = new int[n]; lr = new int[n]; w2 = new int[n];
		update(-1, -1);
		for (int h = 0; h < m; h++)
			if (ii[h] < n)
				update(h, ii[h]);
		sum %= MD;
		println(cnt_ + " " + sum);
	}
}


//package round621;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E2 {
	InputStream is;
	PrintWriter out;
	// 12221
	String INPUT = "";

	void solve()
	{
		// no two cowsとあるので、同じsweetnessのはたかだか100通り
		// 左右の取り分上限を決めてしまえばsweetnessで分割できる
		// 上限が決まっているときの分割しかた
		// ああ1個しか入れられないやんけ
		int n = ni(), m = ni();
		int[] s = na(n);
		int[][] cum = new int[n+1][n+2];
		for(int i = 0;i < m;i++){
			int a = ni(), b = ni();
			cum[a][b]++;
		}

		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				cum[i][j] += cum[i][j-1];
			}
		}

		int[] f = new int[n+1];
		int[] rf = new int[n+1];
		for(int v : s)rf[v]++;

		int mod = 1000000007;
		long ans = 0;
		int maxnum = 0;
		for(int i = 0;i <= n;i++){
			// <= i, <=n-i
			if(i > 0)rf[s[i-1]]--;
			long vt = 0;
			int numt = 0;
			if(i > 0){
				vt = 1;
				for(int j = 1;j <= n;j++){
					long L = cum[j][f[j]];
					long R = cum[j][rf[j]];
					if(L > R){
						long D = L; L = R; R = D;
					}
					if(L >= 1 && R >= 2){
						numt += 2;
						vt = vt * (L*(R-1)) % mod;
					}else if(R >= 1){
						numt++;
						vt = vt * (L+R) % mod;
					}
				}
			}

			if(i > 0)f[s[i-1]]++;
			long v = 1;
			int num = 0;
			for(int j = 1;j <= n;j++){
				long L = cum[j][f[j]];
				long R = cum[j][rf[j]];
				if(L > R){
					long D = L; L = R; R = D;
				}
				if(L >= 1 && R >= 2){
					num += 2;
					v = v * (L*(R-1)) % mod;
				}else if(R >= 1){
					num++;
					v = v * (L+R) % mod;
				}
			}

			if(num > maxnum){
				maxnum = num;
				ans = v;
			}else if(num == maxnum){
				ans += v;
			}
			if(numt == maxnum){
				ans -= vt;
			}
		}
		ans %= mod;
		if(ans < 0)ans += mod;

		out.println(maxnum + " " + ans);
	}

	static int[][] packD(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
		}
		return g;
	}

	void run() throws Exception
	{
//		int n = 5000, m = 5000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(gen.nextInt(3)+1 + " ");
//		}
//		boolean[][] done = new boolean[n+1][n+1];
//		for(int i = 0;i < m;i++){
//			while(true){
//				int x = gen.nextInt(3)+1;
//				int y = gen.nextInt(n)+1;
//				if(!done[x][y]){
//					done[x][y] = true;
//					sb.append(x + " " + y + "\n");
//					break;
//				}
//			}
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E2().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round621;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E3 {
	InputStream is;
	PrintWriter out;
	// 12221
	String INPUT = "";

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	void solve()
	{
		// no two cowsとあるので、同じsweetnessのはたかだか100通り
		// 左右の取り分上限を決めてしまえばsweetnessで分割できる
		// 上限が決まっているときの分割しかた
		// ああ1個しか入れられないやんけ
		int n = ni(), m = ni();
		int[] s = na(n);
		int[][] cum = new int[n+1][n+1];
		for(int i = 0;i < m;i++){
			int a = ni(), b = ni();
			cum[a][b]++;
		}

		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				cum[i][j] += cum[i][j-1];
			}
		}

		int[] f = new int[n+1];
		int[] rf = new int[n+1];
		for(int v : s)rf[v]++;

		int mod = 1000000007;
		long ans = 0;
		int maxnum = 0;
		long vt = 1;

		int[] pf = new int[n+1];
		int[] prf = new int[n+1];
		int[] vals = new int[n+1];
		int[] nums = new int[n+1];
		Arrays.fill(vals, 1);
		int numt = 0;
		for(int i = 0;i <= n;i++){
			// <= i, <=n-i
			if(i > 0)rf[s[i-1]]--;
			if(i > 0){
				for(int j = 1;j <= n;j++){
					if(pf[j] != f[j] || prf[j] != rf[j]){
						vt = vt * invl(vals[j], mod) % mod;
						numt -= nums[j];
						int L = cum[j][f[j]];
						int R = cum[j][rf[j]];
						if(L > R){
							int D = L; L = R; R = D;
						}
						if(L >= 1 && R >= 2){
							numt += 2;
							nums[j] = 2;
							vals[j] = L*(R-1);
							vt = vt * vals[j] % mod;
						}else if(R >= 1){
							numt++;
							nums[j] = 1;
							vals[j] = L+R;
							vt = vt * vals[j] % mod;
						}else{
							nums[j] = 0;
						}
						pf[j] = f[j];
						prf[j] = rf[j];
					}
				}
			}
			long myvt = vt;
			int mynum = i > 0 ? numt : -1;

			if(i > 0)f[s[i-1]]++;
			for(int j = 1;j <= n;j++){
				if(pf[j] != f[j] || prf[j] != rf[j]){
					vt = vt * invl(vals[j], mod) % mod;
					numt -= nums[j];

					int L = cum[j][f[j]];
					int R = cum[j][rf[j]];
					if(L > R){
						int D = L; L = R; R = D;
					}
					if(L >= 1 && R >= 2){
						numt += 2;
						nums[j] = 2;
						vals[j] = L*(R-1);
						vt = vt * vals[j] % mod;
					}else if(R >= 1){
						numt++;
						nums[j] = 1;
						vals[j] = L+R;
						vt = vt * vals[j] % mod;
					}else{
						nums[j] = 0;
					}
					pf[j] = f[j];
					prf[j] = rf[j];
				}
			}

			if(numt > maxnum){
				maxnum = numt;
				ans = vt;
			}else if(numt == maxnum){
				ans += vt;
			}
			if(mynum == maxnum){
				ans -= myvt;
			}
		}
		ans %= mod;
		if(ans < 0)ans += mod;

		out.println(maxnum + " " + ans);
	}

	static int[][] packD(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
		}
		return g;
	}

	void run() throws Exception
	{
//		int n = 5000, m = 5000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(gen.nextInt(3)+1 + " ");
//		}
//		boolean[][] done = new boolean[n+1][n+1];
//		for(int i = 0;i < m;i++){
//			while(true){
//				int x = gen.nextInt(3)+1;
//				int y = gen.nextInt(n)+1;
//				if(!done[x][y]){
//					done[x][y] = true;
//					sb.append(x + " " + y + "\n");
//					break;
//				}
//			}
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E3().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round621;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		// no two cowsとあるので、同じsweetnessのはたかだか100通り
		// 左右の取り分上限を決めてしまえばsweetnessで分割できる
		// 上限が決まっているときの分割しかた
		// ああ1個しか入れられないやんけ
		int n = ni(), m = ni();
		int[] s = na(n);
		int[][] cum = new int[n+1][n+2];
		for(int i = 0;i < m;i++){
			int a = ni(), b = ni();
			cum[a][b]++;
		}

		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				cum[i][j] += cum[i][j-1];
			}
		}

		int[] f = new int[n+1];
		int[] rf = new int[n+1];
		for(int v : s)rf[v]++;

		int[] argmax = new int[n+1];
		outer:
		for(int i = 1;i <= n;i++){
			int pre = -1;
			for(int j = 1;j <= n;j++){
				if(cum[i][j] > cum[i][j-1]){
					if(pre == -1){
						pre = j;
						if(pre <= rf[i]){
							argmax[i] = 1;
						}else{
							continue outer;
						}
					}else{
						if(pre + j <= rf[i]){
							argmax[i] = 2;
							continue outer;
						}
					}
				}
			}
		}

		int mod = 1000000007;
		long ans = 0;
		for(int i = 0;i <= n;i++){
			// <= i, <=n-i
			if(i > 0)rf[s[i-1]]--;
			long vt = 0;
			if(i > 0){
				vt = 1;
				for(int j = 1;j <= n;j++){
					if(argmax[j] == 0)continue;
					long L = cum[j][f[j]];
					long R = cum[j][rf[j]];
					if(L > R){
						long D = L; L = R; R = D;
					}
					long w = argmax[j] == 2 ? L * (R-1) : argmax[j] == 1 ? L + R : 1;
					vt = vt * w % mod;
				}
			}

			if(i > 0)f[s[i-1]]++;
			long v = 1;
			for(int j = 1;j <= n;j++){
				if(argmax[j] == 0)continue;
				long L = cum[j][f[j]];
				long R = cum[j][rf[j]];
				if(L > R){
					long D = L; L = R; R = D;
				}
				long w = argmax[j] == 2 ? L * (R-1) : argmax[j] == 1 ? L + R : 1;
				v = v * w % mod;
			}

			ans += v - vt;
		}
		ans %= mod;
		if(ans < 0)ans += mod;

		long amsum = 0;
		for(int v : argmax)amsum += v;
		out.println(amsum + " " + ans);
	}

	static int[][] packD(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
		}
		return g;
	}

	void run() throws Exception
	{
//		int n = 5000, m = 5000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(gen.nextInt(n)+1 + " ");
//		}
//		boolean[][] done = new boolean[n+1][n+1];
//		for(int i = 0;i < m;i++){
//			while(true){
//				int x = gen.nextInt(1)+1;
//				int y = gen.nextInt(n)+1;
//				if(!done[x][y]){
//					done[x][y] = true;
//					sb.append(x + " " + y + "\n");
//					break;
//				}
//			}
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round621;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E3 {
	InputStream is;
	PrintWriter out;
	// 12221
	String INPUT = "";

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	void solve()
	{
		// no two cowsとあるので、同じsweetnessのはたかだか100通り
		// 左右の取り分上限を決めてしまえばsweetnessで分割できる
		// 上限が決まっているときの分割しかた
		// ああ1個しか入れられないやんけ
		int n = ni(), m = ni();
		int[] s = na(n);
		int[][] cum = new int[n+1][n+1];
		for(int i = 0;i < m;i++){
			int a = ni(), b = ni();
			cum[a][b]++;
		}

		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				cum[i][j] += cum[i][j-1];
			}
		}

		int[] f = new int[n+1];
		int[] rf = new int[n+1];
		for(int v : s)rf[v]++;

		int mod = 1000000007;
		long ans = 0;
		int maxnum = 0;
		long vt = 1;

		int[] pf = new int[n+1];
		int[] prf = new int[n+1];
		int[] vals = new int[n+1];
		Arrays.fill(vals, 1);
		for(int i = 0;i <= n;i++){
			// <= i, <=n-i
			if(i > 0)rf[s[i-1]]--;
			int numt = -1;
			if(i > 0){
				numt = 0;
				for(int j = 1;j <= n;j++){
					if(pf[j] != f[j] || prf[j] != rf[j]){
						vt = vt * invl(vals[j], mod) % mod;

						int L = cum[j][f[j]];
						int R = cum[j][rf[j]];
						if(L > R){
							int D = L; L = R; R = D;
						}
						if(L >= 1 && R >= 2){
							numt += 2;
							vals[j] = L*(R-1);
							vt = vt * vals[j] % mod;
						}else if(R >= 1){
							numt++;
							vals[j] = L+R;
							vt = vt * vals[j] % mod;
						}
					}
				}
			}
			long myvt = vt;

			if(i > 0)f[s[i-1]]++;
			long v = 1;
			int num = 0;
			for(int j = 1;j <= n;j++){
				if(pf[j] != f[j] || prf[j] != rf[j]){
					vt = vt * invl(vals[j], mod) % mod;

					int L = cum[j][f[j]];
					int R = cum[j][rf[j]];
					if(L > R){
						int D = L; L = R; R = D;
					}
					if(L >= 1 && R >= 2){
						num += 2;
						vals[j] = L*(R-1);
						vt = vt * vals[j] % mod;
					}else if(R >= 1){
						num++;
						vals[j] = L+R;
						vt = vt * vals[j] % mod;
					}
				}
			}

			if(num > maxnum){
				maxnum = num;
				ans = vt;
			}else if(num == maxnum){
				ans += vt;
			}
			if(numt == maxnum){
				ans -= myvt;
			}
		}
		ans %= mod;
		if(ans < 0)ans += mod;

		out.println(maxnum + " " + ans);
	}

	static int[][] packD(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
		}
		return g;
	}

	void run() throws Exception
	{
//		int n = 5000, m = 5000;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(gen.nextInt(3)+1 + " ");
//		}
//		boolean[][] done = new boolean[n+1][n+1];
//		for(int i = 0;i < m;i++){
//			while(true){
//				int x = gen.nextInt(3)+1;
//				int y = gen.nextInt(n)+1;
//				if(!done[x][y]){
//					done[x][y] = true;
//					sb.append(x + " " + y + "\n");
//					break;
//				}
//			}
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E3().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

public class E {
    public static void main(String[] args) {
        var scanner = new BufferedScanner();
        var writer = new PrintWriter(new BufferedOutputStream(System.out));

        var n = scanner.nextInt();
        var m = scanner.nextInt();
        var s = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            s[i] = scanner.nextInt();
        }
        var f = new int[m + 1];
        var h = new int[m + 1];
        for (int i = 1; i <= m; i++) {
            f[i] = scanner.nextInt();
            h[i] = scanner.nextInt();
        }
        var ans = solve(n, m, s, f, h);
        writer.println(ans[0] + " " + ans[1]);

        scanner.close();
        writer.flush();
        writer.close();
    }

    static final int MODULO = (int) (1e9 + 7);

    private static int[] solve(int n, int m, int[] s, int[] f, int[] h) {
        var sleepLeft = new int[m + 1];
        var sleepRight = new int[m + 1];
        for (int i = 1; i <= m; i++) {
            {
                var total = 0;
                for (int j = 1; j <= n; j++) {
                    if (s[j] == f[i]) {
                        total++;
                        if (total == h[i]) {
                            sleepLeft[i] = j;
                            break;
                        }
                    }
                }
            }
            {
                var total = 0;
                for (int j = n; j >= 1; j--) {
                    if (s[j] == f[i]) {
                        total++;
                        if (total == h[i]) {
                            sleepRight[i] = j;
                            break;
                        }
                    }
                }
            }
        }
        var bySweet = new HashMap<Integer, List<Integer>>();
        for (int i = 1; i <= m; i++) {
            bySweet.putIfAbsent(f[i], new ArrayList<>());
            bySweet.get(f[i]).add(i);
        }
        var maxCows = Integer.MIN_VALUE;
        var maxWays = Long.MIN_VALUE;
        // first==0表示左边不选
        for (int first = 0; first <= m; first++) {
            var leftStart = 1;
            var leftEnd = sleepLeft[first];
            var rightStart = leftEnd + 1;
            var rightEnd = n;
            var cows = 0;
            var ways = 1L;
            for (var sweet : bySweet.keySet()) {
                var left = 0L;
                var right = 0L;
                var both = 0L;
                for (var i : bySweet.getOrDefault(sweet, List.of())) {
                    if (f[i] != sweet) {
                        continue;
                    }
                    var t = 0;
                    if (sleepLeft[i] >= leftStart && sleepLeft[i] <= leftEnd) {
                        left++;
                        t++;
                    }
                    if (i == first) { // first一定在左边
                        continue;
                    }
                    if (sleepRight[i] >= rightStart && sleepRight[i] <= rightEnd) {
                        right++;
                        t++;
                    }
                    if (t == 2) {
                        both++;
                        left--;
                        right--;
                    }
                }
                if (sweet == f[first] && left > 0) {
                    left = 1; // left被first占据了
                }
                if (left + right + both == 0) {
                    continue;
                }
                long thisWays;
                if (sweet == f[first]) {
                    thisWays = right + both;
                } else {
                    // 尝试任意放两个
                    thisWays = left * (right + both) + both * (right + both - 1);
                }
                if (thisWays == 0) {
                    cows++;
                    if (left == 0) {
                        thisWays = right + both * 2;
                    } else {
                        if (both > 0) {
                            throw new RuntimeException("wtf");
                        }
                        thisWays = left;
                    }
                    ways = (ways * thisWays) % MODULO;
                    continue;
                }
                cows += 2;
                ways = (ways * thisWays) % MODULO;
            }
            if (cows > maxCows) {
                maxCows = cows;
                maxWays = ways;
            } else if (cows == maxCows && cows > 0) {
                maxWays = (maxWays + ways) % MODULO;
            }
        }
        return new int[]{maxCows, (int) maxWays};
    }

    public static class BufferedScanner {
        BufferedReader br;
        StringTokenizer st;

        public BufferedScanner(Reader reader) {
            br = new BufferedReader(reader);
        }

        public BufferedScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    static long gcd(long a, long b) {
        if (a < b) {
            return gcd(b, a);
        }
        while (b > 0) {
            long tmp = b;
            b = a % b;
            a = tmp;
        }
        return a;
    }

    static long inverse(long a, long m) {
        long[] ans = extgcd(a, m);
        return ans[0] == 1 ? (ans[1] + m) % m : -1;
    }

    private static long[] extgcd(long a, long m) {
        if (m == 0) {
            return new long[]{a, 1, 0};
        } else {
            long[] ans = extgcd(m, a % m);
            long tmp = ans[1];
            ans[1] = ans[2];
            ans[2] = tmp;
            ans[2] -= ans[1] * (a / m);
            return ans;
        }
    }

    private static List<Integer> primes(double upperBound) {
        var limit = (int) Math.sqrt(upperBound);
        var isComposite = new boolean[limit + 1];
        var primes = new ArrayList<Integer>();
        for (int i = 2; i <= limit; i++) {
            if (isComposite[i]) {
                continue;
            }
            primes.add(i);
            int j = i + i;
            while (j <= limit) {
                isComposite[j] = true;
                j += i;
            }
        }
        return primes;
    }

}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

public class E {
    public static void main(String[] args) {
        var scanner = new BufferedScanner();
        var writer = new PrintWriter(new BufferedOutputStream(System.out));

        var n = scanner.nextInt();
        var m = scanner.nextInt();
        var s = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            s[i] = scanner.nextInt();
        }
        var f = new int[m + 1];
        var h = new int[m + 1];
        for (int i = 1; i <= m; i++) {
            f[i] = scanner.nextInt();
            h[i] = scanner.nextInt();
        }
        var ans = solve(n, m, s, f, h);
        writer.println(ans[0] + " " + ans[1]);

        scanner.close();
        writer.flush();
        writer.close();
    }

    static final int MODULO = (int) (1e9 + 7);

    static class IntList extends ArrayList<Integer> {}

    private static int[] solve(int n, int m, int[] s, int[] f, int[] h) {
        var sleepL = new int[m + 1];
        var sleepR = new int[m + 1];
        var byFH = new HashMap<Integer, Integer>() {
            public Integer get(int f, int h) {
                return get(hash(f, h));
            }

            void put(int f, int h, int i) {
                put(hash(f, h), i);
            }

            private int hash(int f, int h) {
                return f * (n + 1) + h;
            }
        };
        for (int i = 1; i <= m; i++) {
            byFH.put(f[i], h[i], i);
        }
        {
            var countS = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                countS[s[i]]++;
                var cow = byFH.get(s[i], countS[s[i]]);
                if (cow != null) {
                    sleepL[cow] = i;
                }
            }
            Arrays.fill(countS, 0);
            for (int i = n; i >= 1; i--) {
                countS[s[i]]++;
                var cow = byFH.get(s[i], countS[s[i]]);
                if (cow != null) {
                    sleepR[cow] = i;
                }
            }
        }
        var bySweet = new HashMap<Integer, List<Integer>>();
        for (int i = 1; i <= m; i++) {
            bySweet.putIfAbsent(f[i], new ArrayList<>());
            bySweet.get(f[i]).add(i);
        }
        var sweets = bySweet.keySet().stream().mapToInt(i -> i).toArray();
        var bySweetL = new int[n + 1][];
        var bySweetR = new int[n + 1][];
        for (int sweet : sweets) {
            bySweetL[sweet] = bySweet.get(sweet).stream()
                    .sorted(Comparator.comparingInt(i -> sleepL[i]))
                    .mapToInt(i -> i).toArray();
            bySweetR[sweet] = bySweet.get(sweet).stream()
                    .sorted(Comparator.comparingInt(i -> sleepR[i]))
                    .mapToInt(i -> i).toArray();
        }
        var maxCows = Integer.MIN_VALUE;
        var maxWays = Long.MIN_VALUE;
        // first==0表示左边不选；first一定要用在左边，这样避免计数重复
        for (int first = 0; first <= m; first++) {
            var leftStart = 1;
            var leftEnd = sleepL[first];
            var rightStart = leftEnd + 1;
            var rightEnd = n;
            if (first != 0 && (sleepL[first] < leftStart || sleepL[first] > leftEnd)) {
                continue;
            }
            var cows = 0;
            var ways = 1L;
            for (int sweet : sweets) {
                var left = 0L;
                var right = 0L;
                var both = 0L;
                var left1 = 0L;
                var right1 = 0L;
                var both1 = 0L;
                {
                    var start = binarySearch(bySweetL[sweet], leftStart, sleepL, true, true);
                    var end = binarySearch(bySweetL[sweet], leftEnd, sleepL, false, true);
                    if (start >= 0 && end >= 0) {
                        left1 = end - start + 1;
                        for (int iL = start; iL <= end; iL++) {
                            var i = bySweetL[sweet][iL];
                            var t = 0;
                            if (sleepL[i] >= leftStart && sleepL[i] <= leftEnd) {
                                t++;
                            }
                            if (i == first) { // first一定在左边
                                continue;
                            }
                            if (sleepR[i] >= rightStart && sleepR[i] <= rightEnd) {
                                t++;
                            }
                            if (t == 2) {
                                both1++;
                            }
                        }
                    } else {
                        left1 = 0;
                    }
                    check(left1 >= 0, "left %d,%d,[%d,%d]", first, sweet, start, end);
                }
                {
                    var start = binarySearch(bySweetR[sweet], rightStart, sleepR, true, true);
                    var end = binarySearch(bySweetR[sweet], rightEnd, sleepR, false, true);
                    if (start >= 0 && end >= 0) {
                        right1 = end - start + 1;
                    } else {
                        right1 = 0;
                    }
                    check(right1 >= 0, "right [%d,%d]", start, end);
                }
                // TODO 2020/4/8: both怎么搞？
//                var startI = binarySearch(bySweetL[sweet], leftStart, true,true);
//                for (var i = startI; i < bySweetL[sweet].length; i++) {
                for (var i : bySweetL[sweet]) {
                    var t = 0;
                    if (sleepL[i] >= leftStart && sleepL[i] <= leftEnd) {
                        left++;
                        t++;
                    }
                    if (i == first) { // first一定在左边
                        continue;
                    }
                    if (sleepR[i] >= rightStart && sleepR[i] <= rightEnd) {
                        right++;
                        t++;
                    }
                    if (t == 2) {
                        both++;
                        left--;
                        right--;
                    }
                }
                if (sweet != f[first]) {
                    check(left1 == left + both, "%d,%d,%d<>%d+%d", first, sweet, left1, left, both);
                    check(right1 == right + both, "%d,%d,%d<>%d+%d", first, sweet, right1, right, both);
                }
                if (sweet == f[first]) {
                    left = 1; // left被first占据了
                }
                if (left + right + both == 0) {
                    continue;
                }
                long thisWays;
                if (sweet == f[first]) {
                    thisWays = right + both;
                } else {
                    // 尝试任意放两个
                    thisWays = left * (right + both) + both * (right + both - 1);
                }
                if (thisWays > 0) {
                    cows += 2;
                    ways = (ways * thisWays) % MODULO;
                    continue;
                }
                cows++;
                // 放一个的方案
                thisWays = left + right + both * 2;
                ways = (ways * thisWays) % MODULO;
            }
            if (cows > maxCows) {
                maxCows = cows;
                maxWays = ways;
            } else if (cows == maxCows && cows > 0) {
                maxWays = (maxWays + ways) % MODULO;
            }
        }
        return new int[]{maxCows, (int) maxWays};
    }

    private static void check(boolean predicate, String fmt, Object... args) {
        if (!predicate) {
            throw new RuntimeException(String.format(fmt, args));
        }
    }

    /**
     * @param a  ascending ordered array
     * @param k  key to find
     * @param kf key function
     * @param gt true for gt/gte, false for lt/lte
     * @param e  true for equal, false for unequal
     * @return min i for gt/gte, max i for lt/lte
     */
    private static int binarySearch(int[] a, int k, int[] ks, boolean gt, boolean e) {
        var l = 0;
        var r = a.length - 1;
        var ans = gt ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        while (l <= r) {
            var m = (l + r) / 2;
            var km = ks[a[m]];
            if (gt) { // find min i that a[i]>=/>k
                if (e && km >= k || km > k) {
                    ans = Math.min(ans, m);
                    r = m - 1;
                } else { // a[m]</<=k
                    l = m + 1;
                }
            } else { // find max i that a[i]<=/<k
                if (e && km <= k || km < k) {
                    ans = Math.max(ans, m);
                    l = m + 1;
                } else { // a[m]>/>=k
                    r = m - 1;
                }
            }
        }
        return ans == Integer.MAX_VALUE ? Integer.MIN_VALUE : ans;
    }

    public static class BufferedScanner {
        BufferedReader br;
        StringTokenizer st;

        public BufferedScanner(Reader reader) {
            br = new BufferedReader(reader);
        }

        public BufferedScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    static long gcd(long a, long b) {
        if (a < b) {
            return gcd(b, a);
        }
        while (b > 0) {
            long tmp = b;
            b = a % b;
            a = tmp;
        }
        return a;
    }

    static long inverse(long a, long m) {
        long[] ans = extgcd(a, m);
        return ans[0] == 1 ? (ans[1] + m) % m : -1;
    }

    private static long[] extgcd(long a, long m) {
        if (m == 0) {
            return new long[]{a, 1, 0};
        } else {
            long[] ans = extgcd(m, a % m);
            long tmp = ans[1];
            ans[1] = ans[2];
            ans[2] = tmp;
            ans[2] -= ans[1] * (a / m);
            return ans;
        }
    }

    private static List<Integer> primes(double upperBound) {
        var limit = (int) Math.sqrt(upperBound);
        var isComposite = new boolean[limit + 1];
        var primes = new ArrayList<Integer>();
        for (int i = 2; i <= limit; i++) {
            if (isComposite[i]) {
                continue;
            }
            primes.add(i);
            int j = i + i;
            while (j <= limit) {
                isComposite[j] = true;
                j += i;
            }
        }
        return primes;
    }

}


import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

public class E {
    public static void main(String[] args) {
        var scanner = new BufferedScanner();
        var writer = new PrintWriter(new BufferedOutputStream(System.out));

        var n = scanner.nextInt();
        var m = scanner.nextInt();
        var s = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            s[i] = scanner.nextInt();
        }
        var f = new int[m + 1];
        var h = new int[m + 1];
        for (int i = 1; i <= m; i++) {
            f[i] = scanner.nextInt();
            h[i] = scanner.nextInt();
        }
        var ans = solve(n, m, s, f, h);
        writer.println(ans[0] + " " + ans[1]);

        scanner.close();
        writer.flush();
        writer.close();
    }

    static final int MODULO = (int) (1e9 + 7);

    private static int[] solve(int n, int m, int[] s, int[] f, int[] h) {
        var sleepLeft = new int[m + 1];
        var sleepRight = new int[m + 1];
        var byFH = new HashMap<Integer, Integer>() {
            public Integer get(int f, int h) {
                return get(hash(f, h));
            }

            void put(int f, int h, int i) {
                put(hash(f, h), i);
            }

            private int hash(int f, int h) {
                return f * (n + 1) + h;
            }
        };
        for (int i = 1; i <= m; i++) {
            byFH.put(f[i], h[i], i);
        }
        {
            var countS = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                countS[s[i]]++;
                var cow = byFH.get(s[i], countS[s[i]]);
                if (cow != null) {
                    sleepLeft[cow] = i;
                }
            }
            Arrays.fill(countS, 0);
            for (int i = n; i >= 1; i--) {
                countS[s[i]]++;
                var cow = byFH.get(s[i], countS[s[i]]);
                if (cow != null) {
                    sleepRight[cow] = i;
                }
            }
        }
        for (int i = 1; i <= m; i++) {
//            {
//                var total = 0;
//                for (int j = 1; j <= n; j++) {
//                    if (s[j] == f[i]) {
//                        total++;
//                        if (total == h[i]) {
//                            sleepLeft[i] = j;
//                            break;
//                        }
//                    }
//                }
//            }
//            {
//                var total = 0;
//                for (int j = n; j >= 1; j--) {
//                    if (s[j] == f[i]) {
//                        total++;
//                        if (total == h[i]) {
//                            sleepRight[i] = j;
//                            break;
//                        }
//                    }
//                }
//            }
        }
        var bySweet = new HashMap<Integer, List<Integer>>();
        for (int i = 1; i <= m; i++) {
            bySweet.putIfAbsent(f[i], new ArrayList<>());
            bySweet.get(f[i]).add(i);
        }
        var maxCows = Integer.MIN_VALUE;
        var maxWays = Long.MIN_VALUE;
        // first==0表示左边不选；first一定要用在左边，这样避免计数重复
        for (int first = 0; first <= m; first++) {
            var leftStart = 1;
            var leftEnd = sleepLeft[first];
            var rightStart = leftEnd + 1;
            var rightEnd = n;
            if (first != 0 && (sleepLeft[first] < leftStart || sleepLeft[first] > leftEnd)) {
                continue;
            }
            var cows = 0;
            var ways = 1L;
            for (var entry : bySweet.entrySet()) {
                var sweet = entry.getKey();
                var left = 0L;
                var right = 0L;
                var both = 0L;
                for (var i : entry.getValue()) {
                    var t = 0;
                    if (sleepLeft[i] >= leftStart && sleepLeft[i] <= leftEnd) {
                        left++;
                        t++;
                    }
                    if (i == first) { // first一定在左边
                        continue;
                    }
                    if (sleepRight[i] >= rightStart && sleepRight[i] <= rightEnd) {
                        right++;
                        t++;
                    }
                    if (t == 2) {
                        both++;
                        left--;
                        right--;
                    }
                }
                if (sweet == f[first]) {
                    left = 1; // left被first占据了
                }
                if (left + right + both == 0) {
                    continue;
                }
                long thisWays;
                if (sweet == f[first]) {
                    thisWays = right + both;
                } else {
                    // 尝试任意放两个
                    thisWays = left * (right + both) + both * (right + both - 1);
                }
                if (thisWays > 0) {
                    cows += 2;
                    ways = (ways * thisWays) % MODULO;
                    continue;
                }
                cows++;
                // 放一个的方案
                thisWays = left + right + both * 2;
                ways = (ways * thisWays) % MODULO;
            }
            if (cows > maxCows) {
                maxCows = cows;
                maxWays = ways;
            } else if (cows == maxCows && cows > 0) {
                maxWays = (maxWays + ways) % MODULO;
            }
        }
        return new int[]{maxCows, (int) maxWays};
    }

    public static class BufferedScanner {
        BufferedReader br;
        StringTokenizer st;

        public BufferedScanner(Reader reader) {
            br = new BufferedReader(reader);
        }

        public BufferedScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    static long gcd(long a, long b) {
        if (a < b) {
            return gcd(b, a);
        }
        while (b > 0) {
            long tmp = b;
            b = a % b;
            a = tmp;
        }
        return a;
    }

    static long inverse(long a, long m) {
        long[] ans = extgcd(a, m);
        return ans[0] == 1 ? (ans[1] + m) % m : -1;
    }

    private static long[] extgcd(long a, long m) {
        if (m == 0) {
            return new long[]{a, 1, 0};
        } else {
            long[] ans = extgcd(m, a % m);
            long tmp = ans[1];
            ans[1] = ans[2];
            ans[2] = tmp;
            ans[2] -= ans[1] * (a / m);
            return ans;
        }
    }

    private static List<Integer> primes(double upperBound) {
        var limit = (int) Math.sqrt(upperBound);
        var isComposite = new boolean[limit + 1];
        var primes = new ArrayList<Integer>();
        for (int i = 2; i <= limit; i++) {
            if (isComposite[i]) {
                continue;
            }
            primes.add(i);
            int j = i + i;
            while (j <= limit) {
                isComposite[j] = true;
                j += i;
            }
        }
        return primes;
    }

}