/*
    N行,有M个僵尸,有K个坚果,按顺序从给定线路水平滚出
    坚果撞到僵尸或者边界都会改变路线以45°滚动,问最后多少只僵尸被撞到了
    N<=2000, M<=200000, K<=100000
    
    我之前是按顺序模拟坚果滚动,超时了
    虽然我也是建了list之类的,我知道的是能用x+y,x-y的值来表示直线
    复杂度应该是O(MlogM + K)

    watashi解题报告说可以用链表类似Dancing Links啥的搞到O(M+K),但是编程量巨大
    他自己的做法很神奇!!!!
    反过来做,对僵尸按X排序,从左到右,检查该僵尸会被哪只坚果撞到(其实就是被编号最小的撞到)
    一只僵尸(x,y)可以被3个方向撞到(y=1,n时两个),路线的方程就是
    x - y = k1 , x + y = k2 ,  y = k3
    因此需要找到满足上面方程之一的坚果,而且编号最小的
    直接这样搞,方程很多的,我之前就是这样子搞..

    注意到x-y = k1与x-2(n-1)-y=k1是同一条路线的,所以可以对(x-y)%2(n-1),x+y也一样
    取模了后本来x-y很大的,就变为很小了,而且是可唯一标示出来的
    
    两个点A,B若在同一条路线上,若他们都向下或向上的话,显然
    y1-x1 = y2-x2 mod m  , m-(y1+x1) = m-(y2+x2) mod m 
    若一上一下,就 y1-x1 = m-(y2+x2) mod m
    这样一条路线就能用一个值来表示了,即在点(x,y)处,
    ----------------------------------------------
    |若向下则该路线的值(y-x) mod m        |
    |若向上则该路线的值m-(y+x) mod m    |
    ----------------------------------------------
    为什么能这样表示呢?
    比如向下的直线方程为y-x = k1,向上的为y+x=k2
    他们关于边界对称,则有k1+k2 = m,即k1 = m - k2,所以用K1,m-k2就能唯一表示线路了(曲折的,不是直线)
      \  /
       \/ 
    ------- m/2  下面的那个是引出的,上面的是实际路线,显然这两条直线跟y轴的交点之和k1+k2为m
      /
     /

    在起始处总共也就只会有n-1条向下的,n-1条向上的,n条水平的,这2*(n-1)+n条直线就会铺满整个地图了
    因此可编码为 [0,n-1)的为向下的,[n-1,2(n-1))向上的,[2*(n-1),3*n-2)水平的

    启示:处理好同一条路线怎么用一个值来表示

    枚举点(x,y)可能被几个方向撞到的线路,这些路线就是m+y, (y-x) mod m , m-(y+x) mod m
    最后就用优先队列来搞,取编号最小的路线,因为最先被这个撞到了~~~
    处理好一列后,注意加入新的坚果路线(因为撞了后改变路线了)

    神奇丫神奇丫~~~~


    以上只是我膜拜了watashi的代码后的一点想法而已,建议直接看他的代码~~~
*/

#include
<iostream>
#include
<cstring>
#include
<map>
#include
<algorithm>
#include
<stack>
#include
<queue>
#include
<cmath>
#include
<string>
#include
<cstdlib>
#include
<vector>
#include
<cstdio>
#include
<set>
#include
<list>
#include
<numeric>
#include
<cassert>
#include
<ctime>
#include
<bitset>

using namespace std;

const int MAXN =200000;

pair
<int,int> pt[MAXN];
priority_queue
<int, vector<int>, greater<int> > pq[6000];//最小堆

inline 
int mod(int a, int b) {
    a 
%= b;
    
return a < 0 ? a + b : a;
}


int main()
{
#ifndef ONLINE_JUDGE
    freopen(
"in","r",stdin);
#endif

    
int T, N, M, K;
    
for(scanf("%d"&T); T--; ) {
        scanf(
"%d%d%d"&N, &M, &K);
        
int m = 2*(N-1);

        
for(int k = 0; k < m + N ; k++{
            
while(!pq[k].empty()){
                pq[k].pop();
            }

        }


        
for (int i = 0; i < M; i ++{
            scanf(
"%d%d"&pt[i].first, &pt[i].second);
            pt[i].second 
--;
        }

        sort(pt, pt
+M);

        
for (int i = 0, t; i < K; i ++{
            scanf(
"%d"&t);
            pq[m
+t-1].push(i);
        }

        
        
int lastx = 0, ans = 0;
        vector
<pair<int,int> > r;
        
for(int i = 0; i < M; i ++{
            
int x = pt[i].first , y = pt[i].second;
            
if (x > lastx) {//处理完一列后注意加入新的坚果路线
                lastx = x;
                
for (vector<pair<int,int> >::iterator it = r.begin() ; it != r.end(); it ++{    
                    pq[it
->first].push(it->second);
                }

                r.clear();
            }


            
int j  = -1, t;
            
if(!pq[t = m+y].empty() && (j == -1 || pq[t].top() < pq[j].top())){// horizonal
                j = t;
            }

            
if(!pq[t = mod(y-x, m)].empty() && ( j == -1 || pq[t].top() < pq[j].top()) )//buttom right
                j = t;
            }

            
if(!pq[t = mod(m-(y+x), m)].empty() && ( j == -1 || pq[t].top() < pq[j].top()) )//top right
                j = t;
            }

            
            
if(j == -1){
                
continue;
            }


            ans 
++;
            t 
= pq[j].top();
            pq[j].pop();
            
if(j < m){
                r.push_back(make_pair(mod(m
-j-2*x, m),t));
            }
else {
                j 
-= m;
                
if(j < N/2{//buttom right
                    r.push_back(make_pair(mod(y-x,m),t));
                }
 else {//top right
                    r.push_back(make_pair(mod(m-(y+x),m),t));
                }

            }

        }

        printf(
"%d\n" , ans);
    }

    
return 0;
}