#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>

using namespace std;

const int NMAX = 10 + 1;
const int MMAX = 100000 + 5;

int N, M;
int mat[NMAX][MMAX];

struct Node {
    int st, dr;
    int internal;
    int comps[NMAX][2];
} tree[8 * MMAX];

vector <int> graph[3 * NMAX];

void addEdge(int a, int b) {
    graph[a].push_back(b);
    graph[b].push_back(a);
}

int comps[3 * NMAX];
int currentComp;
void dfs(int node)  {
    comps[node] = currentComp;
    for (auto it: graph[node])
        if (!comps[it])
            dfs(it);
}

void unite(Node &res, const Node a, const Node &b) {
    if (a.st == -1) {
        res = b;
        return ;
    }

    for (int i = 1; i <= 3 * N; ++ i)
        graph[i].clear(), comps[i] = 0;

    //Node a
    int last[2 * NMAX] = {0};
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][0]])
            addEdge(i, last[a.comps[i][0]]);
        last[a.comps[i][0]] = i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][1]])
            addEdge(N + i, last[a.comps[i][1]]);
        last[a.comps[i][1]] = N + i;
    }
    //Node b
    for (int i = 1; i <= 2 * N; ++ i)
        last[i] = 0;
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][0]])
            addEdge(N + i, last[b.comps[i][0]]);
        last[b.comps[i][0]] = N + i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][1]])
            addEdge(2 * N + i, last[b.comps[i][1]]);
        last[b.comps[i][1]] = 2 * N + i;
    }

    //Final dfs left
    currentComp = 0;
    for (int i = 1; i <= N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i][0] = comps[i];
    }

    //Final dfs right
    for (int i = 2 * N + 1; i <= 3 * N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i - 2 * N][1] = comps[i];
    }

    //Final dfs middle
    res.internal = a.internal + b.internal;
    for (int i = N + 1; i <= 2 * N; ++ i)
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
            ++ res.internal;
        }
    res.st = a.st;
    res.dr = b.dr;
}

const int dx[2] = {0, 1};
const int dy[2] = {1, 0};

int where[MMAX];
void build(int node, int st, int dr) {
    tree[node].st = st, tree[node].dr = dr;

    if (dr - st <= 1) {
        for (int i = 1; i <= 2 * N; ++ i)
            graph[i].clear(), comps[i] = 0;

        int nd = 1;
        for (int j = st; j <= dr; ++ j)
            for (int i = 1; i <= N; ++ i, ++ nd)
                for (int k = 0; k < 2; ++ k) {
                    int lin = i + dx[k];
                    int col = j + dy[k];

                    if (lin >= 1 && lin <= N && col >= st && col <= dr && mat[i][j] == mat[lin][col])
                        addEdge(nd, (col - st) * N + lin);
                }

        currentComp = 0;
        for (int i = 1; i <= N; ++ i) {
            if (!comps[i]) {
                ++ currentComp;
                dfs(i);
            }
            tree[node].comps[i][0] = comps[i];
            if (st == dr)
                tree[node].comps[i][1] = comps[i];
        }

        if (st < dr) {
            for (int i = N + 1; i <= 2 * N; ++ i) {
                if (!comps[i]) {
                    ++ currentComp;
                    dfs(i);
                }
                tree[node].comps[i - N][1] = comps[i];
            }
        }

        if (st < dr) {
            build(node << 1, st, st);
            build((node << 1) + 1, dr, dr);
        }

        if (st == dr)
            where[st] = node;
        return ;
    }

    int mid = (st + dr) >> 1;

    build(node << 1, st, mid);
    build((node << 1) + 1, mid, dr);

    unite(tree[node], tree[node << 1], tree[(node << 1) + 1]);
}

Node ans;
void query(int node, int st, int dr) {
    if (tree[node].st == st && tree[node].dr == dr) {
        unite(ans, ans, tree[node]);
        return ;
    }

    int mid = (tree[node].st + tree[node].dr) >> 1;

    if (dr <= mid)
        query(node << 1, st, dr);
    else if (st >= mid)
        query((node << 1) + 1, st, dr);
    else {
        query(node << 1, st, mid);
        query((node << 1) + 1, mid, dr);
    }
}

int main()
{
    //freopen("data.in", "r", stdin);
    ios_base :: sync_with_stdio(false);
    cin.tie(0);

    int Q;
    cin >> N >> M >> Q;
    for (int i = 1; i <= N; ++ i)
        for (int j = 1; j <= M; ++ j)
            cin >> mat[i][j];
    build(1, 1, M);

    while (Q --) {
        int st, dr;
        cin >> st >> dr;

        if (st < dr) {
            ans.st = -1;
            query(1, st, dr);
        }
        else
            ans = tree[where[st]];
        int res = ans.internal;

        vector <int> v;
        for (int i = 1; i <= N; ++ i) {
            v.push_back(ans.comps[i][0]);
            v.push_back(ans.comps[i][1]);
        }

        sort(v.begin(), v.end());
        v.resize(unique(v.begin(), v.end()) - v.begin());

        cout << res + v.size() << '\n';
    }

    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>

using namespace std;

const int NMAX = 10 + 1;
const int MMAX = 100000 + 5;

int N, M;
int mat[NMAX][MMAX];

struct Node {
    int st, dr;
    int internal;
    int comps[NMAX][2];
} tree[4 * MMAX];

vector <int> graph[3 * NMAX];

void addEdge(int a, int b) {
    graph[a].push_back(b);
    graph[b].push_back(a);
}

int comps[3 * NMAX];
int currentComp;
void dfs(int node)  {
    comps[node] = currentComp;
    for (auto it: graph[node])
        if (!comps[it])
            dfs(it);
}

void unite(Node &res, const Node a, const Node &b) {
    if (a.st == -1) {
        res = b;
        return ;
    }

    for (int i = 1; i <= 3 * N; ++ i)
        graph[i].clear(), comps[i] = 0;

    //Node a
    int last[2 * NMAX] = {0};
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][0]])
            addEdge(i, last[a.comps[i][0]]);
        last[a.comps[i][0]] = i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][1]])
            addEdge(N + i, last[a.comps[i][1]]);
        last[a.comps[i][1]] = N + i;
    }
    //Node b
    for (int i = 1; i <= 2 * N; ++ i)
        last[i] = 0;
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][0]])
            addEdge(N + i, last[b.comps[i][0]]);
        last[b.comps[i][0]] = N + i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][1]])
            addEdge(2 * N + i, last[b.comps[i][1]]);
        last[b.comps[i][1]] = 2 * N + i;
    }

    //Final dfs left
    currentComp = 0;
    for (int i = 1; i <= N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i][0] = comps[i];
    }

    //Final dfs right
    for (int i = 2 * N + 1; i <= 3 * N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i - 2 * N][1] = comps[i];
    }

    //Final dfs middle
    res.internal = a.internal + b.internal;
    for (int i = N + 1; i <= 2 * N; ++ i)
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
            ++ res.internal;
        }
    res.st = a.st;
    res.dr = b.dr;
}

const int dx[2] = {0, 1};
const int dy[2] = {1, 0};

int where[NMAX];
void build(int node, int st, int dr) {
    tree[node].st = st, tree[node].dr = dr;

    if (dr - st <= 1) {
        for (int i = 1; i <= 2 * N; ++ i)
            graph[i].clear(), comps[i] = 0;

        int nd = 1;
        for (int j = st; j <= dr; ++ j)
            for (int i = 1; i <= N; ++ i, ++ nd)
                for (int k = 0; k < 2; ++ k) {
                    int lin = i + dx[k];
                    int col = j + dy[k];

                    if (lin >= 1 && lin <= N && col >= st && col <= dr && mat[i][j] == mat[lin][col])
                        addEdge(nd, (col - st) * N + lin);
                }

        currentComp = 0;
        for (int i = 1; i <= N; ++ i) {
            if (!comps[i]) {
                ++ currentComp;
                dfs(i);
            }
            tree[node].comps[i][0] = comps[i];
            if (st == dr)
                tree[node].comps[i][1] = comps[i];
        }

        if (st < dr) {
            for (int i = N + 1; i <= 2 * N; ++ i) {
                if (!comps[i]) {
                    ++ currentComp;
                    dfs(i);
                }
                tree[node].comps[i - N][1] = comps[i];
            }
        }

        if (st < dr) {
            build(node << 1, st, st);
            build((node << 1) + 1, dr, dr);
        }

        if (st == dr)
            where[st] = node;
        return ;
    }

    int mid = (st + dr) >> 1;

    build(node << 1, st, mid);
    build((node << 1) + 1, mid, dr);

    unite(tree[node], tree[node << 1], tree[(node << 1) + 1]);
}

Node ans;
void query(int node, int st, int dr) {
    if (tree[node].st == st && tree[node].dr == dr) {
        unite(ans, ans, tree[node]);
        return ;
    }

    int mid = (tree[node].st + tree[node].dr) >> 1;

    if (dr <= mid)
        query(node << 1, st, dr);
    else if (st >= mid)
        query((node << 1) + 1, st, dr);
    else {
        query(node << 1, st, mid);
        query((node << 1) + 1, mid, dr);
    }
}

int main()
{
    //freopen("data.in", "r", stdin);
    ios_base :: sync_with_stdio(false);
    cin.tie(0);

    int Q;
    cin >> N >> M >> Q;
    for (int i = 1; i <= N; ++ i)
        for (int j = 1; j <= M; ++ j)
            cin >> mat[i][j];
    build(1, 1, M);

    while (Q --) {
        int st, dr;
        cin >> st >> dr;

        if (st < dr) {
            ans.st = -1;
            query(1, st, dr);
        }
        else
            ans = tree[where[st]];
        int res = ans.internal;

        vector <int> v;
        for (int i = 1; i <= N; ++ i) {
            v.push_back(ans.comps[i][0]);
            v.push_back(ans.comps[i][1]);
        }

        sort(v.begin(), v.end());
        v.resize(unique(v.begin(), v.end()) - v.begin());

        cout << res + v.size() << '\n';
    }

    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>

using namespace std;

const int NMAX = 10 + 1;
const int MMAX = 100000 + 5;

int N, M;
int mat[NMAX][MMAX];

struct Node {
    int st, dr;
    int internal;
    int comps[NMAX][2];
} tree[4 * MMAX];

vector <int> graph[3 * NMAX];

void addEdge(int a, int b) {
    graph[a].push_back(b);
    graph[b].push_back(a);
}

int comps[3 * NMAX];
int currentComp;
void dfs(int node)  {
    comps[node] = currentComp;
    for (auto it: graph[node])
        if (!comps[it])
            dfs(it);
}

void unite(Node &res, const Node a, const Node &b) {
    if (a.st == -1) {
        res = b;
        return ;
    }

    for (int i = 1; i <= 3 * N; ++ i)
        graph[i].clear(), comps[i] = 0;

    //Node a
    int last[2 * NMAX] = {0};
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][0]])
            addEdge(i, last[a.comps[i][0]]);
        last[a.comps[i][0]] = i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[a.comps[i][1]])
            addEdge(N + i, last[a.comps[i][1]]);
        last[a.comps[i][1]] = N + i;
    }
    //Node b
    for (int i = 1; i <= 2 * N; ++ i)
        last[i] = 0;
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][0]])
            addEdge(N + i, last[b.comps[i][0]]);
        last[b.comps[i][0]] = N + i;
    }
    for (int i = 1; i <= N; ++ i) {
        if (last[b.comps[i][1]])
            addEdge(2 * N + i, last[b.comps[i][1]]);
        last[b.comps[i][1]] = 2 * N + i;
    }

    //Final dfs left
    currentComp = 0;
    for (int i = 1; i <= N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i][0] = comps[i];
    }

    //Final dfs right
    for (int i = 2 * N + 1; i <= 3 * N; ++ i) {
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
        }
        res.comps[i - 2 * N][1] = comps[i];
    }

    //Final dfs middle
    res.internal = a.internal + b.internal;
    for (int i = N + 1; i <= 2 * N; ++ i)
        if (!comps[i]) {
            ++ currentComp;
            dfs(i);
            ++ res.internal;
        }
    res.st = a.st;
    res.dr = b.dr;
}

const int dx[2] = {0, 1};
const int dy[2] = {1, 0};

void build(int node, int st, int dr) {
    tree[node].st = st, tree[node].dr = dr;

    if (dr - st <= 1) {
        for (int i = 1; i <= 2 * N; ++ i)
            graph[i].clear(), comps[i] = 0;

        int nd = 1;
        for (int j = st; j <= dr; ++ j)
            for (int i = 1; i <= N; ++ i, ++ nd)
                for (int k = 0; k < 2; ++ k) {
                    int lin = i + dx[k];
                    int col = j + dy[k];

                    if (lin >= 1 && lin <= N && col >= st && col <= dr && mat[i][j] == mat[lin][col])
                        addEdge(nd, (col - st) * N + lin);
                }

        currentComp = 0;
        for (int i = 1; i <= N; ++ i) {
            if (!comps[i]) {
                ++ currentComp;
                dfs(i);
            }
            tree[node].comps[i][0] = comps[i];
            if (st == dr)
                tree[node].comps[i][1] = comps[i];
        }

        if (st < dr) {
            for (int i = N + 1; i <= 2 * N; ++ i) {
                if (!comps[i]) {
                    ++ currentComp;
                    dfs(i);
                }
                tree[node].comps[i - N][1] = comps[i];
            }
        }

        if (st < dr) {
            build(node << 1, st, st);
            build((node << 1) + 1, dr, dr);
        }
        return ;
    }

    int mid = (st + dr) >> 1;

    build(node << 1, st, mid);
    build((node << 1) + 1, mid, dr);

    unite(tree[node], tree[node << 1], tree[(node << 1) + 1]);
}

Node ans;
void query(int node, int st, int dr) {
    if (tree[node].st == st && tree[node].dr == dr) {
        unite(ans, ans, tree[node]);
        return ;
    }

    int mid = (tree[node].st + tree[node].dr) >> 1;
    int other = mid;
    if (st + 1 == dr)
        ++ other;

    if (dr <= mid)
        query(node << 1, st, dr);
    else if (st >= other)
        query((node << 1) + 1, st, dr);
    else {
        query(node << 1, st, mid);
        query((node << 1) + 1, other, dr);
    }
}

int main()
{
    //freopen("data.in", "r", stdin);
    ios_base :: sync_with_stdio(false);
    cin.tie(0);

    int Q;
    cin >> N >> M >> Q;
    for (int i = 1; i <= N; ++ i)
        for (int j = 1; j <= M; ++ j)
            cin >> mat[i][j];
    build(1, 1, M);

    while (Q --) {
        int st, dr;
        cin >> st >> dr;

        ans.st = -1;
        query(1, st, dr);

        int res = ans.internal;

        vector <int> v;
        for (int i = 1; i <= N; ++ i) {
            v.push_back(ans.comps[i][0]);
            v.push_back(ans.comps[i][1]);
        }

        sort(v.begin(), v.end());
        v.resize(unique(v.begin(), v.end()) - v.begin());

        cout << res + v.size() << '\n';
    }

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM*2];
inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int a[100],b[100];
int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM << 2];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	static int a[100],b[100];
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	//freopen("811E.in","r",stdin);
	//freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM*3];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	static int a[100];
	static int b[100];
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM*3];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	static int a[100],b[100];
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM << 1];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	static int a[100],b[100];
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	//freopen("811E.in","r",stdin);
	//freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM*3];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int a[100],b[100];
int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
}s[MaxM << 2];

inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	static int a[100],b[100];
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
#ifdef DEBUG
	#define dbg_block(code) {code}
	#define dbg(...) fprintf(stderr,__VA_ARGS__)
#else
	#define dbg_block(code)
	#define dbg(...)
#endif
const int MaxN = 11,MaxM = 100003,MaxQ = 100003;
int n,m,q;
int c[MaxN][MaxM];
struct node{
	int blocks;
	int l[MaxN],r[MaxN];
};//s[MaxM*4];
node* s;
inline void uni(int* fa,int a,int b,int limit) {
	for (int i=1;i<=limit;i++) if (fa[i]==b) fa[i]=a;
}

int a[100],b[100];
int uni2(int* ll,const int* lr,const int* rl,int* rr,const int& rowl,const int& rowr) {
	memset(a,0,sizeof a);
	int midl=(rowl+rowr)/2,midr=midl+1;
	int sum=0,sum2=0;
	for (int i=1;i<=n;i++) a[i]=ll[i],a[i+n]=lr[i],a[i+2*n]=rl[i],a[i+3*n]=rr[i];

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum++;

	for (int i=1;i<=n;i++) if (c[i][midl]==c[i][midr]) uni(a,a[i+n],a[i+2*n],4*n);

	for (int i=1;i<=4*n;i++) b[i]=a[i];sort(b+1,b+4*n+1);
	for (int i=2;i<=4*n;i++) if (b[i]!=b[i-1]) sum2++;

	for (int i=1;i<=n;i++) ll[i]=a[i];
	for (int i=1;i<=n;i++) rr[i]=a[i+3*n];
	return sum-sum2;
}

void build(int p,int l,int r) {
	if (l==r) {
		s[p].blocks=n;
		for (int i=1;i<=n;i++) s[p].l[i]=s[p].r[i]=n*(l-1)+i;
		for (int i=1;i<n;i++)
			if (c[i][l]==c[i+1][l]) uni(s[p].l,s[p].l[i],s[p].l[i+1],n),uni(s[p].r,s[p].r[i],s[p].r[i+1],n),s[p].blocks--;
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	s[p].blocks=s[p*2].blocks+s[p*2+1].blocks;
	for (int i=1;i<=n;i++) s[p].l[i]=s[p*2].l[i],s[p].r[i]=s[p*2+1].r[i];
	s[p].blocks-=uni2(s[p].l,s[p*2].r,s[p*2+1].l,s[p].r,l,r);
}

node query(int p,int l,int r,int ll,int rr) {
	if (ll<=l && r<=rr) return s[p];
	int mid=(l+r)/2;
	node left,right;bool fl=false,fr=false;
	if (ll<=mid) left=query(p*2,l,mid,ll,rr),fl=true;
	if (rr>mid) right=query(p*2+1,mid+1,r,ll,rr),fr=true;
	if (fl && !fr) return left;
	if (!fl && fr) return right;
	node ret;
	ret.blocks=left.blocks+right.blocks;
	for (int i=1;i<=n;i++) ret.l[i]=left.l[i],ret.r[i]=right.r[i];
	ret.blocks-=uni2(ret.l,left.r,right.l,ret.r,mid,mid+1);
	return ret;
}

int main() {
	s=(node*)malloc(MaxM*4*sizeof(node));
	freopen("811E.in","r",stdin);
	freopen("811E.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&(c[i][j]));
		}
	}
	build(1,1,m);
	node t;int l,r;
	for (int i=1;i<=q;i++) {
		scanf("%d%d",&l,&r);
		t=query(1,1,m,l,r);
		printf("%d\n",t.blocks);
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXR=11,MAXC=1e5+1,MAXV=1e6+1,MAXQ=1e5+1;

struct seg{
	int l,r,idx;
};

int conn[2][MAXR][MAXR];
int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u, int cur, int col, int t) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		pred[u]=v;
	}
	FOR(r1,0,R) FOR(r2,r1+1,R) if(find(vert[r1][col])==find(vert[r2][col]) && conn[t][r1][r2]==-1) {
		conn[t][r1][r2]=conn[t][r2][r1]=cur;
	}
}

bool valid(int r, int c, int loc, int hic) {
	return 0<=r && r<R && loc<=c && c<=hic;
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	ms(conn,-1);
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med],med,med,0);
		compCnt--;
	}
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1],c,med,0);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c],c,med,0);
			compCnt	--;
		}
		compLeft[c]=compCnt;
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1],med+1,med+1,1);
		compCnt--;
	}
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1],c,med+1,1);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c],c,med+1,1);
			compCnt	--;
		}
		compRight[c]=compCnt;
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		int diff=0;
		FOR(r1,0,R) if(A[r1][med]==A[r1][med+1]) {
			diff++;
			FOR(r2,0,r1) {
				if(A[r1][med]==A[r2][med] && A[r1][med+1]==A[r2][med+1] && conn[0][r1][r2]!=-1 && conn[0][r1][r2]>=l && conn[1][r1][r2]!=-1 && conn[1][r1][r2]<=r) {
					diff--;
					break;
				}
			}
		}
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);

}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)
#define left kfkdjfd
#define right kdjfkdjfkj

typedef long long ll;
typedef vector<int> vi;

const int MAXR=10,MAXC=1e5;

int R,C,A[MAXR][MAXC],N,Q;
struct STN{
	int comp,lt[MAXR],rt[MAXR],liml,limr;
	void merge(STN ln, STN rn){
		bool check[R][2];
		ms(check,false);
		comp=ln.comp+rn.comp;
		FOR(r,0,R) rn.lt[r]+=R;
		FOR(r,0,R) rn.rt[r]+=R;
		FOR(r,0,R) if(!check[r][0]) merge(0,r,ln,rn,lt,rt,comp,ln.limr,rn.liml,check,ln.rt[r]);
		FOR(r,0,R) if(!check[r][1]) merge(1,r,ln,rn,lt,rt,comp,ln.limr,rn.liml,check,rn.lt[r]);
		liml=ln.liml;
		limr=rn.limr;
		FOR(r,0,R) lt[r]=ln.lt[r];
		FOR(r,0,R) rt[r]=rn.rt[r];
	}
	void operator=(int c) {
		comp=0;
		liml=limr=c;
		lt[0]=rt[0]=comp++;
		FOR(r,1,R) lt[r]=rt[r]= A[r][c]==A[r-1][c]?lt[r-1]:comp++;
	}
	void merge(int t, int r, STN &ln, STN &rn, int lt[], int rt[], int &comp, int liml, int limr, bool check[][2], int ncomp) {
		if(t==0) {
			int curcomp=ln.rt[r];
			ln.rt[r]=ncomp;
			check[r][0]=true;
			FOR(rr,0,R) if(ln.lt[rr]==curcomp) ln.lt[rr]=ncomp;
			FOR(rr,0,R) if(ln.rt[rr]==curcomp && !check[rr][0]) {
				merge(t,rr,ln,rn,lt,rt,comp,liml,limr,check,ncomp);
			}
			if(!check[r][1] && A[r][liml]==A[r][limr]) {
				merge(1,r,ln,rn,lt,rt,comp,liml,limr,check,ncomp);
				comp--;
			}
		} else {
			int curcomp=rn.lt[r];
			rn.lt[r]=ncomp;
			check[r][1]=true;
			FOR(rr,0,R) if(rn.rt[rr]==curcomp) rn.rt[rr]=ncomp;
			FOR(rr,0,R) if(rn.lt[rr]==curcomp && !check[rr][1]) {
				merge(t,rr,ln,rn,lt,rt,comp,liml,limr,check,ncomp);
			}
			if(!check[r][0] && A[r][liml]==A[r][limr]) {
				merge(0,r,ln,rn,lt,rt,comp,liml,limr,check,ncomp);
				comp--;
			}
		}
	}
};

STN ST[4*MAXC];
void STB(int id = 1,int l = 0,int r = N){
	if(r - l < 2){
		ST[id] = l;
		return;
	}
	int M = (l+r)>>1, L=id<<1, R=L|1;
	STB(L, l, M); STB(R, M, r);
	ST[id].merge(ST[L],ST[R]);
}

STN STQ(int x,int y,int id = 1,int l = 0,int r = N){
	if(x == l && y == r)	return ST[id];
	int M = (l+r)>>1, L=id<<1, R=L|1;
	if(x>=M)	return STQ(x,y,R,M,r);
	if(y<=M)	return STQ(x,y,L,l,M);
	STN res,ln=STQ(x, M, L, l, M),rn=STQ(M, y, R, M, r);
	return res.merge(ln, rn), res;
}

int main() {
	rii(R,C);ri(Q);
	N=C;
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	STB();
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		printf("%d\n",STQ(l-1,r).comp);
	}
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)
#define left kfkdjfd
#define right kdjfkdjfkj

typedef long long ll;
typedef vector<int> vi;

const int MAXR=10,MAXC=1e5;

int R,C,A[MAXR][MAXC],N,Q;
struct STN{
	int comp,lt[MAXR],rt[MAXR],liml,limr;
	void merge(STN ln, STN rn){
		bool check[R][2];
		ms(check,false);
		comp=ln.comp+rn.comp;
		int maxC=0;
		FOR(r,0,R) maxC=max(maxC,ln.lt[r]);
		FOR(r,0,R) maxC=max(maxC,ln.rt[r]);
		FOR(r,0,R) rn.lt[r]+=maxC+1;
		FOR(r,0,R) rn.rt[r]+=maxC+1;
		FOR(r,0,R) if(!check[r][0]) merge(0,r,ln,rn,comp,ln.limr,rn.liml,check,ln.rt[r]);
		FOR(r,0,R) if(!check[r][1]) merge(1,r,ln,rn,comp,ln.limr,rn.liml,check,rn.lt[r]);
		liml=ln.liml;
		limr=rn.limr;
		FOR(r,0,R) lt[r]=ln.lt[r];
		FOR(r,0,R) rt[r]=rn.rt[r];
	}
	void operator=(int c) {
		comp=0;
		liml=limr=c;
		lt[0]=rt[0]=comp++;
		FOR(r,1,R) lt[r]=rt[r]= A[r][c]==A[r-1][c]?lt[r-1]:comp++;
	}
	void merge(int t, int r, STN &ln, STN &rn, int &comp, int liml, int limr, bool check[][2], int ncomp) {
		if(t==0) {
			int curcomp=ln.rt[r];
			ln.rt[r]=ncomp;
			check[r][0]=true;
			FOR(rr,0,R) if(ln.lt[rr]==curcomp) ln.lt[rr]=ncomp;
			FOR(rr,0,R) if(ln.rt[rr]==curcomp && !check[rr][0]) {
				merge(t,rr,ln,rn,comp,liml,limr,check,ncomp);
			}
			if(!check[r][1] && A[r][liml]==A[r][limr]) {
				merge(1,r,ln,rn,comp,liml,limr,check,ncomp);
				comp--;
			}
		} else {
			int curcomp=rn.lt[r];
			rn.lt[r]=ncomp;
			check[r][1]=true;
			FOR(rr,0,R) if(rn.rt[rr]==curcomp) rn.rt[rr]=ncomp;
			FOR(rr,0,R) if(rn.lt[rr]==curcomp && !check[rr][1]) {
				merge(t,rr,ln,rn,comp,liml,limr,check,ncomp);
			}
			if(!check[r][0] && A[r][liml]==A[r][limr]) {
				merge(0,r,ln,rn,comp,liml,limr,check,ncomp);
				comp--;
			}
		}
	}
};

STN ST[4*MAXC];
void STB(int id = 1,int l = 0,int r = N){
	if(r - l < 2){
		ST[id] = l;
		return;
	}
	int M = (l+r)>>1, L=id<<1, R=L|1;
	STB(L, l, M); STB(R, M, r);
	ST[id].merge(ST[L],ST[R]);
}

STN STQ(int x,int y,int id = 1,int l = 0,int r = N){
	if(x == l && y == r)	return ST[id];
	int M = (l+r)>>1, L=id<<1, R=L|1;
	if(x>=M)	return STQ(x,y,R,M,r);
	if(y<=M)	return STQ(x,y,L,l,M);
	STN res,ln=STQ(x, M, L, l, M),rn=STQ(M, y, R, M, r);
	return res.merge(ln, rn), res;
}

int main() {
	rii(R,C);ri(Q);
	N=C;
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	STB();
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		printf("%d\n",STQ(l-1,r).comp);
	}
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXR=11,MAXC=1e5+1,MAXV=1e6+1,MAXQ=1e5+1;

struct seg{
	int l,r,idx;
};

int conn[2][MAXR][MAXR];
int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		pred[u]=v;
	}
}

bool valid(int r, int c, int loc, int hic) {
	return 0<=r && r<R && loc<=c && c<=hic;
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	ms(conn,-1);
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med]);
		compCnt--;
	}
	FOR(r1,0,R) FOR(r2,r1+1,R) if(find(vert[r1][med])==find(vert[r2][med]) && conn[0][r1][r2]==-1) {
		conn[0][r1][r2]=conn[0][r2][r1]=med;
	}
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compLeft[c]=compCnt;
		FOR(r1,0,R) FOR(r2,r1+1,R) if(find(vert[r1][med])==find(vert[r2][med]) && conn[0][r1][r2]==-1) {
			conn[0][r1][r2]=conn[0][r2][r1]=c;
		}
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1]);
		compCnt--;
	}
	FOR(r1,0,R) FOR(r2,r1+1,R) if(find(vert[r1][med+1])==find(vert[r2][med+1]) && conn[1][r1][r2]==-1) {
		conn[1][r1][r2]=conn[1][r2][r1]=med+1;
	}
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compRight[c]=compCnt;
		FOR(r1,0,R) FOR(r2,r1+1,R) if(find(vert[r1][med+1])==find(vert[r2][med+1]) && conn[1][r1][r2]==-1) {
			conn[1][r1][r2]=conn[1][r2][r1]=c;
		}
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		int diff=0;
		FOR(r1,0,R) if(A[r1][med]==A[r1][med+1]) {
			diff++;
			FOR(r2,0,r1) {
				if(A[r1][med]==A[r2][med] && A[r1][med+1]==A[r2][med+1] && conn[0][r1][r2]!=-1 && conn[0][r1][r2]>=l && conn[1][r1][r2]!=-1 && conn[1][r1][r2]<=r) {
					diff--;
					break;
				}
			}
		}
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);

}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)
#define left kfkdjfd
#define right kdjfkdjfkj

typedef long long ll;
typedef vector<int> vi;

const int MAXR=10,MAXC=1e5;

int R,C,A[MAXR][MAXC],N,Q;
struct STN{
	int comp,lt[MAXR],rt[MAXR],liml,limr;
	void merge(STN ln, STN rn){
		bool check[R][2];
		ms(check,false);
		comp=ln.comp+rn.comp;
		FOR(r,0,R) rn.lt[r]+=R;
		FOR(r,0,R) rn.rt[r]+=R;
		FOR(r,0,R) if(!check[r][0]) merge(0,r,ln,rn,comp,ln.limr,rn.liml,check,-1*ln.rt[r]);
		FOR(r,0,R) if(!check[r][1]) merge(1,r,ln,rn,comp,ln.limr,rn.liml,check,-1*rn.lt[r]);
		liml=ln.liml;
		limr=rn.limr;
		FOR(r,0,R) lt[r]=-1*ln.lt[r];
		FOR(r,0,R) rt[r]=-1*rn.rt[r];
	}
	void operator=(int c) {
		comp=0;
		liml=limr=c;
		lt[0]=rt[0]=comp++;
		FOR(r,1,R) lt[r]=rt[r]= A[r][c]==A[r-1][c]?lt[r-1]:comp++;
	}
	void merge(int t, int r, STN &ln, STN &rn, int &comp, int liml, int limr, bool check[][2], int ncomp) {
		if(t==0) {
			int curcomp=ln.rt[r];
			ln.rt[r]=ncomp;
			check[r][0]=true;
			FOR(rr,0,R) if(ln.lt[rr]==curcomp) ln.lt[rr]=ncomp;
			FOR(rr,0,R) if(ln.rt[rr]==curcomp && !check[rr][0]) {
				merge(t,rr,ln,rn,comp,liml,limr,check,ncomp);
			}
			if(!check[r][1] && A[r][liml]==A[r][limr]) {
				merge(1,r,ln,rn,comp,liml,limr,check,ncomp);
				comp--;
			}
		} else {
			int curcomp=rn.lt[r];
			rn.lt[r]=ncomp;
			check[r][1]=true;
			FOR(rr,0,R) if(rn.rt[rr]==curcomp) rn.rt[rr]=ncomp;
			FOR(rr,0,R) if(rn.lt[rr]==curcomp && !check[rr][1]) {
				merge(t,rr,ln,rn,comp,liml,limr,check,ncomp);
			}
			if(!check[r][0] && A[r][liml]==A[r][limr]) {
				merge(0,r,ln,rn,comp,liml,limr,check,ncomp);
				comp--;
			}
		}
	}
};

STN ST[4*MAXC];
void STB(int id = 1,int l = 0,int r = N){
	if(r - l < 2){
		ST[id] = l;
		return;
	}
	int M = (l+r)>>1, L=id<<1, R=L|1;
	STB(L, l, M); STB(R, M, r);
	ST[id].merge(ST[L],ST[R]);
}

STN STQ(int x,int y,int id = 1,int l = 0,int r = N){
	if(x == l && y == r)	return ST[id];
	int M = (l+r)>>1, L=id<<1, R=L|1;
	if(x>=M)	return STQ(x,y,R,M,r);
	if(y<=M)	return STQ(x,y,L,l,M);
	STN res,ln=STQ(x, M, L, l, M),rn=STQ(M, y, R, M, r);
	return res.merge(ln, rn), res;
}

int main() {
	rii(R,C);ri(Q);
	N=C;
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	STB();
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		printf("%d\n",STQ(l-1,r).comp);
	}
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)
#define left kfkdjfd
#define right kdjfkdjfkj

typedef long long ll;
typedef vector<int> vi;

const int MAXR=12,MAXC=1e5+2,MAXV=1e6+2,MAXQ=1e5+2;

struct seg{
	int l,r,idx;
};

bool in[MAXC];
int nxt[2][MAXR][MAXR],prv[2][MAXR][MAXR];
int conn[2][MAXR][MAXR];
int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		pred[u]=v;
	}
}

bool valid(int r, int c, int loc, int hic) {
	return 0<=r && r<R && loc<=c && c<=hic;
}

void upd(int t, int col, int cur) {
	FOR(r1,0,R) {
		int r2=nxt[t][r1][r1];
		while(r2<R) {
			if(find(vert[r1][col])==find(vert[r2][col]) && conn[t][r1][r2]==-1) {
				conn[t][r1][r2]=conn[t][r2][r1]=cur;
				if(prv[t][r1][r2]>=0) nxt[t][r1][prv[t][r1][r2]]=nxt[t][r1][r2];
				if(nxt[t][r1][r2]< R) prv[t][r1][nxt[t][r1][r2]]=prv[t][r1][r2];
			}
			r2=nxt[t][r1][r2];
		}
	}
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	ms(conn,-1);
	ms(in,false);
	FOR(i,0,V.size()) in[V[i].l]=true,in[V[i].r]=true;
	FOR(t,0,2) FOR(r1,0,R) FOR(r2,0,R) nxt[t][r1][r2]=r2+1;
	FOR(t,0,2) FOR(r1,0,R) FOR(r2,0,R) prv[t][r1][r2]=r2-1;
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med]);
		compCnt--;
	}
	upd(0,med,med);
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compLeft[c]=compCnt;
		if(in[c]) upd(0,med,c);
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1]);
		compCnt--;
	}
	upd(1,med+1,med+1);
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compRight[c]=compCnt;
		if(in[c]) upd(1,med+1,c);
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		int diff=0;
		FOR(r1,0,R) if(A[r1][med]==A[r1][med+1]) {
			diff++;
			FOR(r2,0,r1) {
				if(A[r1][med]==A[r2][med] && A[r1][med+1]==A[r2][med+1] && conn[0][r1][r2]!=-1 && conn[0][r1][r2]>=l && conn[1][r1][r2]!=-1 && conn[1][r1][r2]<=r) {
					diff--;
					break;
				}
			}
		}
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);

}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXR=11,MAXC=1e5+1,MAXV=1e6+1,MAXQ=1e5+1;

struct seg{
	int l,r,idx;
};

int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		merge(v,u);
	}
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med]);
		compCnt--;
	}
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compLeft[c]=compCnt;
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1]);
		compCnt--;
	}
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compRight[c]=compCnt;
	}
	int diff=0;
	FOR(r,0,R) if(A[r][med]==A[r][med+1] && find(vert[r][med])!=find(vert[r][med+1])) {
		merge(vert[r][med],vert[r][med+1]);
		diff++;
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);

}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXR=12,MAXC=1e5+2,MAXV=1e6+2,MAXQ=1e5+2;

struct seg{
	int l,r,idx;
};

int nxt[2][MAXR][MAXR],prv[2][MAXR][MAXR];
int conn[2][MAXR][MAXR];
int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		pred[u]=v;
	}
}

bool valid(int r, int c, int loc, int hic) {
	return 0<=r && r<R && loc<=c && c<=hic;
}

void upd(int t, int col, int cur) {
	FOR(r1,0,R) {
		int r2=nxt[t][r1][r1];
		while(r2<R) {
			if(find(vert[r1][col])==find(vert[r2][col]) && conn[t][r1][r2]==-1) {
				conn[t][r1][r2]=conn[t][r2][r1]=cur;
				if(prv[t][r1][r2]>=0) nxt[t][r1][prv[t][r1][r2]]=nxt[t][r1][r2];
				if(nxt[t][r1][r2]< R) prv[t][r1][nxt[t][r1][r2]]=prv[t][r1][r2];
			}
			//printf("%d %d\n",r2,nxt[t][r1][r2]);
			r2=nxt[t][r1][r2];
		}
	}
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	ms(conn,-1);
	FOR(t,0,2) FOR(r1,0,R) FOR(r2,0,R) nxt[t][r1][r2]=r2+1;
	FOR(t,0,2) FOR(r1,0,R) FOR(r2,0,R) prv[t][r1][r2]=r2-1;
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med]);
		compCnt--;
	}
	upd(0,med,med);
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compLeft[c]=compCnt;
		upd(0,med,c);
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1]);
		compCnt--;
	}
	upd(1,med+1,med+1);
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compRight[c]=compCnt;
		upd(1,med+1,c);
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		int diff=0;
		FOR(r1,0,R) if(A[r1][med]==A[r1][med+1]) {
			diff++;
			FOR(r2,0,r1) {
				if(A[r1][med]==A[r2][med] && A[r1][med+1]==A[r2][med+1] && conn[0][r1][r2]!=-1 && conn[0][r1][r2]>=l && conn[1][r1][r2]!=-1 && conn[1][r1][r2]<=r) {
					diff--;
					break;
				}
			}
		}
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);

}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)
#define left kfkdjfd
#define right kdjfkdjfkj

typedef long long ll;
typedef vector<int> vi;

const int MAXR=12,MAXC=1e5+2,MAXV=1e6+2,MAXQ=1e5+2,MAXN=1e6+2;

struct seg{
	int l,r,idx;
};

bool in[MAXC];
int nxt[2][MAXR],prv[2][MAXR],lst[2][MAXN];
int conn[2][MAXR][MAXR];
int ans[MAXQ];
int vert[MAXR][MAXC];
int pred[MAXV],rnk[MAXV];
int R,C,A[MAXR][MAXC],Q;
vector<seg> V;

void initUF() {
	FOR(i,0,R*C) {
		pred[i]=i;
		rnk[i]=0;
	}
}

int find(int v) {
	if(v==pred[v]) return v;
	else return pred[v]=find(pred[v]);
}

void merge(int v, int u) {
	v=find(v);
	u=find(u);
	if(rnk[v]<rnk[u]) {
		pred[v]=u;
		rnk[u]++;
	} else if(rnk[v]>rnk[u]) {
		pred[u]=v;
		rnk[v]++;
	} else {
		rnk[v]++;
		pred[u]=v;
	}
}

bool valid(int r, int c, int loc, int hic) {
	return 0<=r && r<R && loc<=c && c<=hic;
}

void upd(int t, int col, int cur) {
	FOR(r1,0,R) {
		int r2=nxt[t][r1];
		while(r2!=-1) {
			if(find(vert[r1][col])==find(vert[r2][col]) && conn[t][r1][r2]==-1) {
				conn[t][r1][r2]=conn[t][r2][r1]=cur;
				if(prv[t][r2]!=-1) nxt[t][prv[t][r2]]=nxt[t][r2];
				if(nxt[t][r2]!=-1) prv[t][nxt[t][r2]]=prv[t][r2];
			}
			r2=nxt[t][r2];
		}
	}
}

void f(int lo, int med, int hi, vector<seg> V) {
	int compLeft[MAXC];
	int compRight[MAXC];
	int compCnt=R;
	int vcnt=0;
	initUF();
	ms(conn,-1);
	ms(in,false);
	ms(lst,-1);
	ms(nxt,-1);
	ms(prv,-1);
	FOR(i,0,V.size()) in[V[i].l]=true,in[V[i].r]=true;
	FOR(t,0,2) FORR(r,R-1,-1) {
		if(lst[t][A[r][med+t]]!=-1) nxt[t][r]=lst[t][A[r][med+t]];
		lst[t][A[r][med+t]]=r;
	}
	FOR(t,0,2) FOR(r,0,R) {
		if(nxt[t][r]!=-1) prv[t][nxt[t][r]]=r;
	}
	FOR(r,0,R) vert[r][med]=vcnt++;
	FOR(r,0,R-1) if(A[r][med]==A[r+1][med] && find(vert[r][med])!=find(vert[r+1][med])) {
		merge(vert[r][med],vert[r+1][med]);
		compCnt--;
	}
	upd(0,med,med);
	compLeft[med]=compCnt;
	FORR(c,med-1,lo-1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c+1] && find(vert[r][c])!=find(vert[r][c+1])) {
			merge(vert[r][c],vert[r][c+1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compLeft[c]=compCnt;
		if(in[c]) upd(0,med,c);
	}
	compCnt=R;
	FOR(r,0,R) vert[r][med+1]=vcnt++;
	FOR(r,0,R-1) if(A[r][med+1]==A[r+1][med+1] && find(vert[r][med+1])!=find(vert[r+1][med+1])) {
		merge(vert[r][med+1],vert[r+1][med+1]);
		compCnt--;
	}
	upd(1,med+1,med+1);
	compRight[med+1]=compCnt;
	FOR(c,med+2,hi+1) {
		compCnt+=R;
		FOR(r,0,R) vert[r][c]=vcnt++;
		FOR(r,0,R) if(A[r][c]==A[r][c-1] && find(vert[r][c])!=find(vert[r][c-1])) {
			merge(vert[r][c],vert[r][c-1]);
			compCnt--;
		}
		FOR(r,0,R-1) if(A[r][c]==A[r+1][c] && find(vert[r][c])!=find(vert[r+1][c])) {
			merge(vert[r][c],vert[r+1][c]);
			compCnt	--;
		}
		compRight[c]=compCnt;
		if(in[c]) upd(1,med+1,c);
	}
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		int diff=0;
		FOR(r1,0,R) if(A[r1][med]==A[r1][med+1]) {
			diff++;
			FOR(r2,0,r1) {
				if(A[r1][med]==A[r2][med] && A[r1][med+1]==A[r2][med+1] && conn[0][r1][r2]!=-1 && conn[0][r1][r2]>=l && conn[1][r1][r2]!=-1 && conn[1][r1][r2]<=r) {
					diff--;
					break;
				}
			}
		}
		ans[idx]=compLeft[l]+compRight[r]-diff;
	}
}

void f2(int c, vector<seg> V) {
	int cnt=R;
	FOR(r,0,R-1) if(A[r][c]==A[r+1][c]) cnt--;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		ans[idx]=cnt;
	}
}

void solve(int lo, int hi, vector<seg> V) {
	if(lo>hi) return;
	if(lo==hi) {
		f2(lo,V);
		return;
	}
	int med=(lo+hi)/2;
	vector<seg> left,right,middle;
	FOR(i,0,V.size()) {
		int l=V[i].l;
		int r=V[i].r;
		int idx=V[i].idx;
		if(r<=med) left.pb({l,r,idx});
		else if(l>med) right.pb({l,r,idx});
		else middle.pb({l,r,idx});
	}
	f(lo,med,hi,middle);
	solve(lo,med,left);
	solve(med+1,hi,right);
}

int main() {
	rii(R,C);ri(Q);
	FOR(r,0,R) FOR(c,0,C) ri(A[r][c]);
	FOR(q,0,Q) {
		int l,r;
		rii(l,r);
		l--,r--;
		V.pb({l,r,q});
	}
	solve(0,C-1,V);
	FOR(q,0,Q) printf("%d\n",ans[q]);
}


#include <bits/stdc++.h>
using namespace std;
int grid[10][10],dp[11][11],dx[] = {0,0,1,-1},dy[] = {1,-1,0,0};
int n,m,q;
pair<int,int>par[15][15];
void dsu(){
	for(int i = 0;i < 15;i++)
		for(int j = 0;j < 15;j++)
			par[i][j] = make_pair(i,j);
}
pair<int,int> get(pair<int,int>u){
	return par[u.first][u.second] == u ? u : par[u.first][u.second] = get(par[u.first][u.second]);
}
int solve(int to,int st){
	for(int i = st;i <= to ;i++)
		for(int j = 0;j < n;j++)
			for(int k = 0;k < 4;k++){
				int nx = i + dx[k],ny = j + dy[k];
				if(nx < st || nx > to || ny >= n || ny < 0)
					continue;
				if(grid[ny][nx] == grid[j][i]){
					pair<int,int>t = get(make_pair(ny,nx));
					par[t.first][t.second] = get(make_pair(j,i));
				}
			}
	int ret = 0;
	for(int i = st;i <= to;i++)
		for(int j = 0;j < n;j++)
			ret+=(par[j][i] == make_pair(j,i));
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	scanf("%d%d%d",&n,&m,&q);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++)
			scanf("%d",&grid[i][j]);
	for(int i = 0;i < m;i++)
		for(int j = i;j < m;j++){
			dsu();
			dp[i][j] = solve(j,i);
		}
	for(int i = 0;i < q;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		a--;b--;
		printf("%d\n",dp[a][b]);
	}
}


#include <bits/stdc++.h>
using namespace std;
int col[10][100000];
vector<vector<int> >v;
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
	node(){
		comp = 0;
		l = 0;r = 0;
		lp.clear();rp.clear();
	}
	int getlp(int a){
		return lp[a] == a ? a : lp[a] = getlp(lp[a]);
	}
	int getrp(int a){
		return rp[a] == a? a : rp[a] == getrp(rp[a]);
	}
}seg[400000];
node merge(const node x,const node y){
	node a = x;
	node b = y;
	if(a.comp <= 0)return b;
	if(b.comp <= 0)return a;
	node temp;
	map<int,int> &mp = a.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = a.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	temp.comp = a.comp + b.comp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.r],d = col[i][b.l];
		if(v[i][a.r] == v[i][b.l] && temp.getlp(c) != temp.getlp(d)){
			temp.comp--;
			temp.lp[temp.getlp(c)] = temp.getlp(d);
		}
	}
	node ret;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.l];
		ret.lp[c] = temp.getlp(c);
	}
	for(int i = 0;i < v.size();i++){
		int c = col[i][b.r];
		ret.lp[c] = temp.getlp(c);
	}
	ret.comp = temp.comp;
	ret.l = a.l;
	ret.r = b.r;
	//cout << ret.l << " " << ret.r << endl;
	return ret;
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++)
			seg[c].lp[col[i][l]] = seg[c].rp[col[i][l]] = col[i][l];
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].lp[seg[c].getlp(a)] = seg[c].getlp(b);
		}
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].rp[seg[c].getrp(a)] = seg[c].getrp(b);
		}
		map<int,int> &mp = seg[c].lp;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			if(i->first == seg[c].getlp(i->second))seg[c].comp++;
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
	//cout << seg[2*c + 1].l << " " << seg[2*c + 2].r << endl;
	//cout << seg[c].comp << endl;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l > e || r < s){
		ret.comp = -1;
		return ret;
	}
	if(l >= s && r <= e){
		return seg[c];
	}
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	ret = merge(a,b);
//	cout << l << " " << r << endl;
//	cout << a.comp << "  " << b.comp << endl;
//	cout << ret.comp << endl;
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lel = 0;
	scanf("%d%d%d",&n,&m,&q);
	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lel++;
		}
	build(0,0,v[0].size() - 1);
	//return 0;
	//cout << get(0,0,v.size() - 1,0,1).comp << endl;
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,v[0].size() - 1,l,r).comp);
		//exit(0);
	}
}


#include <bits/stdc++.h>
using namespace std;
vector<vector<int> >v;
int col[10][100000],par[1000000];
struct node{
	int comp,l,r;
	vector<pair<int,int> >v;
}seg[400000];
int get(int u){
	return par[u] == u ? u : par[u] = get(par[u]);
}
node merge(node x,node y){
	node ret;
	if(x.comp <= 0)return y;
	if(y.comp <= 0)return x;
	ret.comp = x.comp + y.comp;
	for(int i = 0;i < x.v.size();i++)
		par[x.v[i].first] = x.v[i].second;
	x.v.clear();
	for(int i = 0;i < y.v.size();i++)
		par[y.v[i].first] = y.v[i].second;
	y.v.clear();
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.r],b = col[i][y.l];
		if(v[i][x.r] != v[i][y.l])continue;
		ret.comp-=get(a)!=get(b);
		par[get(a)] = get(b);
	}
	bool vis[1000000] = {0};
	ret.l = x.l;ret.r = y.r;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.l],b = col[i][y.r];
		if(!vis[a])
			ret.v.push_back(make_pair(a,get(a)));
		vis[a] = 1;
		if(vis[b])continue;
			ret.v.push_back(make_pair(b,get(b)));
		vis[b] = 1;
	}
	return ret;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	ret.comp = -1;
	if(l > e || r < s)return ret;
	if(l >= s && r <= e)return seg[c];
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return merge(a,b);
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			par[x] = x;
		}
		for(int i = 0;i < v.size() - 1;i++){
			int x = col[i][l],y = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				par[get(x)] = get(y);
		}
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			seg[c].v.push_back(make_pair(x,get(x)));
			seg[c].comp+=x == get(x);
		}
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lol = 0;
	scanf("%d%d%d",&n,&m,&q);
 	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lol++;
		}
	build(0,0,m);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,m,l,r).comp);
	}
}


#include <bits/stdc++.h>
using namespace std;
int col[10][100000];
vector<vector<int> >v;
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
	node(){
		comp = 0;
		l = 0;r = 0;
		lp.clear();rp.clear();
	}
	int getlp(int a){
		return lp[a] == a ? a : lp[a] = getlp(lp[a]);
	}
	int getrp(int a){
		return rp[a] == a? a : rp[a] == getrp(rp[a]);
	}
}seg[400000];
node merge(node a,node b){
	if(a.comp == -1)return b;
	if(b.comp == -1)return a;
	node temp;
	map<int,int> &mp = a.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = a.getrp(i->first);
	mp = a.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = a.getlp(i->first);
	mp = b.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = b.getlp(i->first);
	mp = b.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = b.getrp(i->first);
	temp.comp = a.comp + b.comp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.r],d = col[i][b.l];
		if(v[i][a.r] == v[i][b.l] && temp.getlp(c) != temp.getlp(d)){
			temp.comp--;
			seg[c].lp[temp.getlp(c)] = temp.getlp(d);
		}
	}
	node ret;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.l];
		ret.lp[c] = temp.getlp(c);
	}
	for(int i = 0;i < v.size();i++){
		int c = col[i][b.r];
		ret.lp[c] = temp.getlp(c);
	}
	ret.comp = temp.comp;
	ret.l = a.l;
	ret.r = b.r;
	return ret;
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++)
			seg[c].lp[col[i][l]] = seg[c].rp[col[i][l]] = col[i][l];
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].lp[seg[c].getlp(a)] = seg[c].getlp(b);
		}
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].rp[seg[c].getrp(a)] = seg[c].getrp(b);
		}
		map<int,int> &mp = seg[c].lp;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			if(i->first == i->second)seg[c].comp++;
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l > e || r < s){
		ret.comp = -1;
		return ret;
	}
	if(l >= s && r<= e){
		return seg[c];
	}
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return ret = merge(a,b);
}
int main(){
//	freopen("readin.txt","r",stdin);
	int n,m,q,lel = 0;
	scanf("%d%d%d",&n,&m,&q);
	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lel++;
		}
	build(0,0,v.size() - 1);
	//cout << get(0,0,v.size() - 1,0,1).comp << endl;
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,v.size() - 1,l,r).comp);
	}
}


#include <bits/stdc++.h>
using namespace std;
vector<vector<int> >v;
int col[10][100000],par[1000000];
struct node{
	int comp,l,r;
	vector<pair<int,int> >v;
}seg[400000];
int get(int u){
	return par[u] == u ? u : par[u] = get(par[u]);
}
node merge(node x,node y){
	node ret;
	if(x.comp <= 0)return y;
	if(y.comp <= 0)return x;
	ret.comp = x.comp + y.comp;
	for(int i = 0;i < x.v.size();i++)
		par[x.v[i].first] = x.v[i].second;
	x.v.clear();
	for(int i = 0;i < y.v.size();i++)
		par[y.v[i].first] = y.v[i].second;
	y.v.clear();
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.r],b = col[i][y.l];
		if(v[i][x.r] != v[i][y.l])continue;
		ret.comp-=get(a)!=get(b);
		par[get(a)] = get(b);
	}
	ret.l = x.l;ret.r = y.r;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.l],b = col[i][y.r];
		ret.v.push_back(make_pair(a,get(a)));
		ret.v.push_back(make_pair(b,get(b)));
	}
	return ret;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	ret.comp = -1;
	if(l > e || r < s)return ret;
	if(l >= s && r <= e)return seg[c];
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return merge(a,b);
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			par[x] = x;
		}
		for(int i = 0;i < v.size() - 1;i++){
			int x = col[i][l],y = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				par[get(x)] = get(y);
		}
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			seg[c].v.push_back(make_pair(x,get(x)));
			seg[c].comp+=x == get(x);
		}
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lol = 0;
	scanf("%d%d%d",&n,&m,&q);
 	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lol++;
		}
	build(0,0,m);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,m,l,r).comp);
	}
}


#include <bits/stdc++.h>
using namespace std;
vector<vector<int> >v;
int col[10][100000],par[1000000];
struct node{
	int comp,l,r;
	vector<pair<int,int> >v;
}seg[400000];
int get(int u){
	return par[u] == u ? u : par[u] = get(par[u]);
}
node merge(const node x,const node y){
	node ret;
	if(x.comp <= 0)return y;
	if(y.comp <= 0)return x;
	ret.comp = x.comp + y.comp;
	for(int i = 0;i < x.v.size();i++)
		par[x.v[i].first] = x.v[i].second;
	for(int i = 0;i < y.v.size();i++)
		par[y.v[i].first] = y.v[i].second;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.r],b = col[i][y.l];
		if(v[i][x.r] != v[i][y.l])continue;
		ret.comp-=get(a)!=get(b);
		par[get(a)] = get(b);
	}
	ret.l = x.l;ret.r = y.r;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.l],b = col[i][y.r];
		ret.v.push_back(make_pair(a,get(a)));
		ret.v.push_back(make_pair(b,get(b)));
	}
	return ret;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	ret.comp = -1;
	if(l > e || r < s)return ret;
	if(l >= s && r <= e)return seg[c];
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return merge(a,b);
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			par[x] = x;
		}
		for(int i = 0;i < v.size() - 1;i++){
			int x = col[i][l],y = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				par[get(x)] = get(y);
		}
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			seg[c].v.push_back(make_pair(x,get(x)));
			seg[c].comp+=x == get(x);
		}
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lol = 0;
	scanf("%d%d%d",&n,&m,&q);
 	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lol++;
		}
	build(0,0,m);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,m,l,r).comp);
	}
}


#include <bits/stdc++.h>
using namespace std;
int col[10][100000];
vector<vector<int> >v;
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
	node(){
		comp = 0;
		l = 0;r = 0;
		lp.clear();rp.clear();
	}
	int getlp(int a){
		return lp[a] == a ? a : lp[a] = getlp(lp[a]);
	}
	int getrp(int a){
		return rp[a] == a? a : rp[a] == getrp(rp[a]);
	}
}seg[400000];
node merge(const node x,const node y){
	node a = x;
	node b = y;
	if(a.comp <= 0)return b;
	if(b.comp <= 0)return a;
	node temp;
	map<int,int> &mp = a.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = a.getrp(i->first);
	mp = a.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = a.getlp(i->first);
	mp = b.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = b.getlp(i->first);
	mp = b.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = b.getrp(i->first);
	temp.comp = a.comp + b.comp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.r],d = col[i][b.l];
		if(v[i][a.r] == v[i][b.l] && temp.getlp(c) != temp.getlp(d)){
			temp.comp--;
			temp.lp[temp.getlp(c)] = temp.getlp(d);
		}
	}
	node ret;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.l];
		ret.lp[c] = temp.getlp(c);
	}
	for(int i = 0;i < v.size();i++){
		int c = col[i][b.r];
		ret.lp[c] = temp.getlp(c);
	}
	ret.comp = temp.comp;
	ret.l = a.l;
	ret.r = b.r;
//	cout << ret.l << " " << ret.r << endl;
	return ret;
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++)
			seg[c].lp[col[i][l]] = seg[c].rp[col[i][l]] = col[i][l];
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].lp[seg[c].getlp(a)] = seg[c].getlp(b);
		}
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].rp[seg[c].getrp(a)] = seg[c].getrp(b);
		}
		map<int,int> &mp = seg[c].lp;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			if(i->first == seg[c].getlp(i->second))seg[c].comp++;
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
//	cout << seg[2*c + 1].l << " " << seg[2*c + 2].r << endl;
//	cout << seg[c].comp << endl;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l > e || r < s){
		ret.comp = -1;
		return ret;
	}
	if(l >= s && r <= e){
		return seg[c];
	}
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	ret = merge(a,b);
//	cout << l << " " << r << endl;
//	cout << a.comp << "  " << b.comp << endl;
//	cout << ret.comp << endl;
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lel = 0;
	scanf("%d%d%d",&n,&m,&q);
	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lel++;
		}
	build(0,0,v.size() - 1);
	//return 0;
	//cout << get(0,0,v.size() - 1,0,1).comp << endl;
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,v.size() - 1,l,r).comp);
		//exit(0);
	}
}


#include <bits/stdc++.h>
using namespace std;
int col[10][100000];
vector<vector<int> >v;
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
	int getlp(int a){
		return lp[a] == a ? a : lp[a] = getlp(lp[a]);
	}
	int getrp(int a){
		return rp[a] == a? a : rp[a] == getrp(rp[a]);
	}
}seg[400000];
node merge(const node x,const node y){
	node a = x;
	node b = y;
	if(a.comp <= 0)return b;
	if(b.comp <= 0)return a;
	node temp;
	map<int,int> &mp = a.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = a.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	temp.comp = a.comp + b.comp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.r],d = col[i][b.l];
		if(v[i][a.r] == v[i][b.l] && temp.getlp(c) != temp.getlp(d)){
			temp.comp--;
			temp.lp[temp.getlp(c)] = temp.getlp(d);
		}
	}
	mp = temp.lp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][b.r],d = col[i][b.l],e = col[i][a.r];
		temp.rp[c] = temp.lp[c];
		temp.lp.erase(c);
		temp.lp.erase(d);
		temp.lp.erase(e);
	}
	temp.l = a.l;
	temp.r = b.r;
	//cout << ret.l << " " << ret.r << endl;
	return temp;
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++)
			seg[c].lp[col[i][l]] = col[i][l];
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].lp[seg[c].getlp(a)] = seg[c].getlp(b);
		}
		map<int,int> &mp = seg[c].lp;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			seg[c].rp[i->first] = i->second;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			seg[c].comp+=i->first == seg[c].getlp(i->second);
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
	//cout << seg[2*c + 1].l << " " << seg[2*c + 2].r << endl;
	//cout << seg[c].comp << endl;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l > e || r < s){
		ret.comp = -1;
		return ret;
	}
	if(l >= s && r <= e){
		return seg[c];
	}
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	ret = merge(a,b);
//	cout << l << " " << r << endl;
//	cout << a.comp << "  " << b.comp << endl;
//	cout << ret.comp << endl;
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lel = 0;
	scanf("%d%d%d",&n,&m,&q);
	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lel++;
		}
	build(0,0,v[0].size() - 1);
	//return 0;
	//cout << get(0,0,v.size() - 1,0,1).comp << endl;
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,v[0].size() - 1,l,r).comp);
		//exit(0);
	}
}


#include <bits/stdc++.h>
using namespace std;
vector<vector<int> >v;
int col[10][100000],par[1000000];
struct node{
	int comp,l,r;
	vector<pair<int,int> >v;
}seg[400000];
int get(int u){
	return par[u] == u ? u : par[u] = get(par[u]);
}
node merge(node x,node y){
	node ret;
	if(x.comp <= 0)return y;
	if(y.comp <= 0)return x;
	ret.comp = x.comp + y.comp;
	for(int i = 0;i < x.v.size();i++)
		par[x.v[i].first] = x.v[i].second;
	x.v.clear();
	for(int i = 0;i < y.v.size();i++)
		par[y.v[i].first] = y.v[i].second;
	y.v.clear();
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.r],b = col[i][y.l];
		if(v[i][x.r] != v[i][y.l])continue;
		ret.comp-=get(a)!=get(b);
		par[get(a)] = get(b);
	}
	bool vis[1000000] = {0};
	ret.l = x.l;ret.r = y.r;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.l],b = col[i][y.r];
		if(!vis[a])
			ret.v.push_back(make_pair(a,get(a)));
		vis[a] = 1;
		if(vis[b])continue;
			ret.v.push_back(make_pair(b,get(b)));
		vis[b] = 1;
	}
	return ret;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	ret.comp = -1;
	if(l > e || r < s)return ret;
	if(l >= s && r <= e)return seg[c];
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return merge(a,b);
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			par[x] = x;
		}
		for(int i = 0;i < v.size() - 1;i++){
			int x = col[i][l],y = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				par[get(x)] = get(y);
		}
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			seg[c].v.push_back(make_pair(x,get(x)));
			seg[c].comp+=x == get(x);
		}
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lol = 0;
	scanf("%d%d%d",&n,&m,&q);
 	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lol++;
		}
	build(0,0,m - 1);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,m - 1,l,r).comp);
	}
}


#include <bits/stdc++.h>
using namespace std;
int col[10][100000];
vector<vector<int> >v;
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
	int getlp(int a){
		return lp[a] == a ? a : lp[a] = getlp(lp[a]);
	}
	int getrp(int a){
		return rp[a] == a? a : rp[a] == getrp(rp[a]);
	}
}seg[400000];
node merge(const node x,const node y){
	node a = x;
	node b = y;
	if(a.comp <= 0)return b;
	if(b.comp <= 0)return a;
	node temp;
	map<int,int> &mp = a.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = a.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	mp = b.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		temp.lp[i->first] = i->second;
	temp.comp = a.comp + b.comp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][a.r],d = col[i][b.l];
		if(v[i][a.r] == v[i][b.l] && temp.getlp(c) != temp.getlp(d)){
			temp.comp--;
			temp.lp[temp.getlp(c)] = temp.getlp(d);
		}
	}
	mp = temp.lp;
	for(int i = 0;i < v.size();i++){
		int c = col[i][b.r];
		temp.rp[c] = temp.lp[c];
		temp.lp.erase(c);
	}
	temp.l = a.l;
	temp.r = b.r;
	//cout << ret.l << " " << ret.r << endl;
	return temp;
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++)
			seg[c].lp[col[i][l]] = col[i][l];
		for(int i = 0;i < v.size() - 1;i++){
			int a = col[i][l],b = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				seg[c].lp[seg[c].getlp(a)] = seg[c].getlp(b);
		}
		map<int,int> &mp = seg[c].lp;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			seg[c].rp[i->first] = i->second;
		for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
			seg[c].comp+=i->first == seg[c].getlp(i->second);
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
	//cout << seg[2*c + 1].l << " " << seg[2*c + 2].r << endl;
	//cout << seg[c].comp << endl;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l > e || r < s){
		ret.comp = -1;
		return ret;
	}
	if(l >= s && r <= e){
		return seg[c];
	}
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	ret = merge(a,b);
//	cout << l << " " << r << endl;
//	cout << a.comp << "  " << b.comp << endl;
//	cout << ret.comp << endl;
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lel = 0;
	scanf("%d%d%d",&n,&m,&q);
	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lel++;
		}
	build(0,0,v[0].size() - 1);
	//return 0;
	//cout << get(0,0,v.size() - 1,0,1).comp << endl;
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,v[0].size() - 1,l,r).comp);
		//exit(0);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int v[10][N],col[10][N],lol,n,m,q;
int par[40*N + 5];
struct node{
	int sz,l,r;
	unordered_map<int,int>lp,rp;
	node(){
		sz = 0;l = r = -1;lp.clear(),rp.clear();
	}
}seg[4*N];
int get(int u){return par[u] == u ? u : par[u] = get(par[u]);}
node merge(const node a,const node b){
	node ret;
	for(auto i : a.lp)par[i.first] = i.second,par[i.second] = i.second;
	for(auto i : b.lp)par[i.first] = i.second,par[i.second] = i.second;
	for(auto i : a.rp)par[i.first] = i.second,par[i.second] = i.second;
	for(auto i : b.rp)par[i.first] = i.second,par[i.second] = i.second;
	ret.sz = a.sz + b.sz;
	for(int i = 0;i < n;i++){
		int x = get(col[i][a.r]),y = get(col[i][b.l]);
		if(x == y || v[i][a.r] != v[i][b.l])continue;
		par[x] = y;
		ret.sz--;
	}
	ret.l = a.l;
	ret.r = b.r;
	for(auto i : a.lp)ret.lp[i.first] = get(i.first);
	for(auto i : b.rp)ret.rp[i.first] = get(i.first);
	return ret;
}
void build(int c,int l,int r){
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < n;i++)par[col[i][l]] = col[i][l];
		for(int i = 0;i < n - 1;i++)if(v[i][l] == v[i + 1][l])par[get(col[i + 1][l])] = get(col[i][l]);
		for(int i = 0;i < n;i++)seg[c].lp[col[i][l]] = seg[c].rp[col[i][l]] = get(col[i][l]),seg[c].sz+=col[i][l] == par[col[i][l]];
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l >= s && r <= e)return seg[c];
	if((l + r)/2 >= e)ret = get(2*c + 1,l,(l + r)/2,s,e);
	else if((l + r)/2 < s)ret = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	else ret = merge(get(2*c + 1,l,(l + r)/2,s,e),get(2*c + 2,(l + r)/2 + 1,r,s,e));
	return ret;
}
int main(){
	freopen("readin.txt","r",stdin);
	scanf("%d%d%d",&n,&m,&q);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++)
			scanf("%d",&v[i][j]),col[i][j] = lol++;
	build(0,0,m - 1);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%d\n",get(0,0,m - 1,--l,--r).sz);
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int v[10][N],col[10][N],lol,n,m,q;
int par[40*N + 5];
struct node{
	int sz,l,r;
	unordered_map<int,int>lp,rp;
	node(){
		sz = 0;l = r = -1;lp.clear(),rp.clear();
	}
}seg[N];
int get(int u){return par[u] == u ? u : par[u] = get(par[u]);}
node merge(const node a,const node b){
	node ret;
	for(auto i : a.lp)par[i.first] = i.second;
	for(auto i : b.lp)par[i.first] = i.second;
	for(auto i : a.rp)par[i.first] = i.second;
	for(auto i : b.rp)par[i.first] = i.second;
	ret.sz = a.sz + b.sz;
	for(int i = 0;i < n;i++){
		int x = get(col[i][a.r]),y = get(col[i][b.l]);
		if(x == y || v[i][a.r] != v[i][b.l])continue;
		par[x] = y;
		ret.sz--;
	}
	ret.l = a.l;
	ret.r = b.r;
	for(auto i : a.lp)ret.lp[i.first] = get(i.first);
	for(auto i : b.rp)ret.rp[i.first] = get(i.first);
	return ret;
}
void build(int c,int l,int r){
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < n;i++)par[col[i][l]] = col[i][l];
		for(int i = 0;i < n - 1;i++)if(v[i][l] == v[i + 1][l])par[get(col[i + 1][l])] = get(col[i][l]);
		for(int i = 0;i < n;i++)seg[c].lp[col[i][l]] = seg[c].rp[col[i][l]] = get(col[i][l]),seg[c].sz+=col[i][l] == par[col[i][l]];
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
node get(int c,int l,int r,int s,int e){
	node ret;
	if(l >= s && r <= e)return seg[c];
	if((l + r)/2 >= e)ret = get(2*c + 1,l,(l + r)/2,s,e);
	else if((l + r)/2 < s)ret = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	else ret = merge(get(2*c + 1,l,(l + r)/2,s,e),get(2*c + 2,(l + r)/2 + 1,r,s,e));
	return ret;
}
int main(){
	//freopen("readin.txt","r",stdin);
	scanf("%d%d%d",&n,&m,&q);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++)
			scanf("%d",&v[i][j]),col[i][j] = lol++;
	build(0,0,m - 1);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%d\n",get(0,0,m - 1,--l,--r).sz);
	}
}


#include <bits/stdc++.h>
using namespace std;
vector<vector<int> >v;
int col[10][100000],par[1000000];
struct node{
	int comp,l,r;
	map<int,int>lp,rp;
}seg[400000];
int get(int u){
	return par[u] == u ? u : par[u] = get(par[u]);
}
node merge(node x,node y){
	node ret;
	if(x.comp <= 0)return y;
	if(y.comp <= 0)return x;
	ret.comp = x.comp + y.comp;
	map<int,int> &mp = x.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		par[i->first] = i->second;
	x.lp.clear();
	mp = x.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		par[i->first] = i->second;
	x.rp.clear();
	mp = y.lp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		par[i->first] = i->second;
	y.lp.clear();
	mp = y.rp;
	for(map<int,int>::iterator i = mp.begin();i != mp.end();i++)
		par[i->first] = i->second;
	y.rp.clear();
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.r],b = col[i][y.l];
		if(v[i][x.r] != v[i][y.l])continue;
		ret.comp-=get(a)!=get(b);
		par[get(b)] = get(a);
	}
	bool vis[1000000] = {0};
	ret.l = x.l;ret.r = y.r;
	for(int i = 0;i < v.size();i++){
		int a = col[i][x.l],b = col[i][y.r];
		ret.lp[a] = get(a);
		ret.rp[b] = get(b);
	}
	return ret;
}
node get(int c,int l,int r,int s,int e){
	node ret;
	ret.comp = -1;
	if(l > e || r < s)return ret;
	if(l >= s && r <= e)return seg[c];
	node a = get(2*c + 1,l,(l + r)/2,s,e);
	node b = get(2*c + 2,(l + r)/2 + 1,r,s,e);
	return merge(a,b);
}
void build(int c,int l,int r){
	seg[c].comp = 0;
	if(l == r){
		seg[c].l = seg[c].r = l;
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			par[x] = x;
		}
		for(int i = 0;i < v.size() - 1;i++){
			int x = col[i][l],y = col[i + 1][l];
			if(v[i][l] == v[i + 1][l])
				par[get(y)] = get(x);
		}
		for(int i = 0;i < v.size();i++){
			int x = col[i][l];
			seg[c].comp+=x==get(x);
			seg[c].lp[x] = seg[c].rp[x] = get(x);
		}
		return;
	}
	build(2*c + 1,l,(l + r)/2);
	build(2*c + 2,(l + r)/2 + 1,r);
	seg[c] = merge(seg[2*c + 1],seg[2*c + 2]);
}
int main(){
	//freopen("readin.txt","r",stdin);
	int n,m,q,lol = 0;
	scanf("%d%d%d",&n,&m,&q);
 	v.resize(n);
	for(int i = 0;i < n;i++)
		for(int j = 0;j < m;j++){
			int a;
			scanf("%d",&a);
			v[i].push_back(a);
			col[i][j] = lol++;
			par[col[i][j]] = col[i][j];
		}
	build(0,0,m - 1);
	for(int i = 0;i < q;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		l--;r--;
		printf("%d\n",get(0,0,m - 1,l,r).comp);
	}
}