#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define vi vector<ll>
#define rep(i,a,b) for(int i=a; i<b; ++i)
#define pb push_back
#define endl '\n'
#define sa(x) sort((x).begin(), (x).end());
#define int long long
#define ii pair<ll, ll>
#define vii vector<ii>
#define x first
#define y second

template<typename T, typename U> static inline void amin(T &x, U y){ if(y<x) x=y; }
template<typename T, typename U> static inline void amax(T &x, U y){ if(x<y) x=y; }
template<typename T,typename U> std::ostream& operator<<(std::ostream& out, std::pair<T,U> a) {out<<" ("<<a.x<<" "<<a.y<<") "; return out;}
template<typename T,typename U> std::istream& operator>>(std::istream& in, std::pair<T,U> &a) {in>>a.x>>a.y; return in;}
template<typename T> static inline void sd(vector<T> &x) {sort(all(x), greater<T>()) ; }

const int N = 2e5+5;
int n, q;
string s, f;

const int maxn=N;
struct node{
	int v,mn,mx;
	int lazy=0;
	bool flag;
	//use assign to set leaf valoes depending upon array values
	void assign(int val)
	{
		mn=mx=v=val;
	}
	//use merge to set parent's values in relation to its children
	void merge(node &l,node &r)
	{
		mx=max(l.mx,r.mx);
		mn=min(l.mn,r.mn);
		v=l.v+r.v;
	}
}zero;
struct segtree{
	node t[4*maxn];
public:
	//if a node has lazy tag then its info is correct but its children's info
	//is old, so pushdown() before going into children
	void reset(int k){
		rep(i,0,4*k){
			t[i].v=t[i].mx=t[i].mn=t[i].lazy=t[i].flag=0;
		}
	}
	void pushdown(int v,int tl,int tr)
	{
		int ln=v*2;
		int rn=v*2+1;
		int tm=(tl+tr)/2;
		if(t[v].flag){
			apply(ln,tl,tm,t[v].lazy);
			apply(rn,tm+1,tr,t[v].lazy);
			t[v].flag=0;
		}
	}
	//apply() is an auxillary function to apply range update and set lazy tag
	void apply(int v,int tl,int tr,int val)
	{
		//so as not to flag the leaf nodes
		if(tl!=tr){
			t[v].flag=1;
			t[v].lazy=val;
		}
		t[v].mx=t[v].mn=val;
		t[v].v=(tr-tl+1)*val;
	}
	void build(int v, int tl, int tr) {
		if (tl == tr) {
			t[v].assign(f[tl]-'0');
			return;
		} else {
			int tm = (tl + tr) / 2;
			build(v*2, tl, tm);
			build(v*2+1, tm+1, tr);
			t[v].merge(t[v*2],t[v*2+1]);
		}
	}

	node query(int v, int tl, int tr, int l, int r) {
		if (l > tr || r < tl)
			return zero;
		if (l <= tl && tr <= r) {
			return t[v];
		}
		pushdown(v,tl,tr);
		int tm = (tl + tr) / 2;
		node a,b,ans;
		a=query(v*2, tl, tm, l, r);
		b=query(v*2+1, tm+1, tr, l, r);
		ans.merge(a,b);
		return ans;
	}

	void rupd(int v, int tl, int tr, int l, int r, int val)
	{
		if(l > tr || r < tl)
			return;
		if(l <= tl && tr <= r && t[v].mx==t[v].mn)
		{
			apply(v,tl,tr,val);
			return;
		}
		pushdown(v,tl,tr);
		int tm = (tl + tr)/2;
		rupd(v*2,tl,tm,l,r,val);
		rupd(v*2+1,tm+1,tr,l,r,val);
		t[v].merge(t[v*2],t[v*2+1]);
	}
}t;
 
// int a[N];


void solve(){
	cin>>n>>q>>s>>f;
	vii qq(q);
	t.reset(n);
	rep(i,0,q){
		cin>>qq[q-i-1];
		// cout<<qq[q-i-1]<<endl;;
	}
	t.build(1, 0, n-1);
	rep(i,0,q){
		int l=qq[i].x, r=qq[i].y;
		l--, r--;
		node nn = t.query(1, 0, n-1, l, r);
		int total = r-l+1, ones = nn.v, half = total/2;
		if(total%2==0) half--;
		if(ones <= half){
			t.rupd(1, 0, n-1, l, r, 0);
		}
		else if (total - ones <= half){
			t.rupd(1, 0, n-1, l, r, 1);	
		}
		else{
			cout<<"NO\n";
			return;
		}
	}
	rep(i,0,n){
		if(t.query(1, 0, n-1, i, i).v != s[i]-'0'){
			cout<<"NO\n";
			return;
		}
	}
	cout<<"YES\n";


}

signed main()
{
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int testcases=1;
	cin>>testcases;
	while(testcases--){
		solve();
	}
	return 0;	
}
