Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"sort"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	for scanner.Scan() {
		n, _ := strconv.Atoi(scanner.Text())
		if n == 0 {
			break
		}
		hr := make([]entry, 0)
		for i := 0; i < n; i++ {
			scanner.Scan()
			buf := strings.Split(scanner.Text(), " ")
			first, _ := strconv.Atoi(buf[0])
			second, _ := strconv.Atoi(buf[1])
			mt := entry{first, second}
			hr = append(hr, mt)
		}
		scanner.Scan()
		m, _ := strconv.Atoi(scanner.Text())
		for i := 0; i < m; i++ {
			scanner.Scan()
			buf := strings.Split(scanner.Text(), " ")
			first, _ := strconv.Atoi(buf[0])
			second, _ := strconv.Atoi(buf[1])
			mt := entry{first, second}
			hr = append(hr, mt)
		}
		sort.Sort(ByFirst(hr))
		fmt.Println(LIS(hr))
	}
}

type entry struct {
	first, second int
}

type ByFirst []entry

func(f ByFirst) Len() int {
	return len(f)
}

func (f ByFirst) Swap(i, j int) {
	f[i], f[j] = f[j], f[i]
}

func (f ByFirst) Less(i, j int) bool {
	return f[i].first < f[j].first
}

func LIS(hr []entry) int {
	n := len(hr)
	lis := make([]int, n)
	lis[n-1] = 1
	for i := n-2; i > -1; i-- {
		m := 0
		for j := i+1; j < n; j++ {
			if hr[i].first < hr[j].first && hr[i].second < hr[j].second && lis[j] > m {
				m = lis[j]
			}
		}
		lis[i] = m+1
	}
	return lis[0]
}

C++: //LIS
#include<iostream>
using namespace std;
int main(){
  int n,h1[101],r1[101],m,h2[101],r2[101],k;
  int data[201],data2[201],dp[201];

  data[0]=data2[0]=0;

  
  while(cin >>n && n!=0){
    dp[0]=0;

    k=0;
    for(int i=1;i<=n;i++){
      cin >>h1[i]>>r1[i];
      data[i]=h1[i];data2[i]=r1[i];}
    cin >>m;
    for(int i=1;i<=m;i++){
      cin >>h2[i]>>r2[i];
      data[i+n]=h2[i];data2[i+n]=r2[i];}
    int key;
    for(int i=1;i<n+m+1;i++){
      key=i;
      for(int j=i;j<n+m+1;j++){
	if(data[key]>data[j])key=j;}
      swap(data[i],data[key]);
      swap(data2[i],data2[key]);}

    for(int i=1;i<n+m+1;i++){
      key=0;
      for(int j=0;j<i;j++){
	
	if( (  data[j]<data[i] && data2[j]<data2[i] )  && dp[j]>dp[key]) {
	  key=j;
	}
      }
      dp[i] = dp[key]+1;
    }
   
    for(int i=1;i<n+m+1;i++){
      if(dp[i]>k)k=dp[i];

    }
    cout<<k<<endl;
    /*
	for(int i=0;i<n+m+1;i++){
      cout<<dp[i]<<endl;
      cout<<data[i]<<" "<<data2[i]<<endl;}
    */
  }
}

C++: #include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

class Matryoshka{
public:
  int h;
  int r; 

  bool operator < ( const Matryoshka &m ) const {
    if( h < m.h  ){
      return true;
    }else{
      return false;
    }
  }
};

typedef vector< Matryoshka > Dolls;

void MaxSubSequenceLength( Dolls &d, vector< int > &ans ){
  ans[0] = 0;
  for(int i = 1; i < d.size(); i++){
    int maxSub = -1, maxj;

    for(int j = i - 1; j >= 0; j--){
      if( d[j].r < d[i].r && d[j].h < d[i].h ){
	if( maxSub < ans[j] ){
	  maxj = j;
	  maxSub = ans[j];
	}
      }
    }

    ans[i] = ans[maxj] + 1;
  }
}

void InputMatryoshka( Dolls &d, int num ){
  for(int i = 0; i < num; i++){
    Matryoshka m;
    
    cin >> m.h;
    cin >> m.r;
    d.push_back( m );
  }
}

int main(void){
  while( 1 ){
    int n, m;
    Dolls dolls;
    Matryoshka matryoBanpei;
    int maxMatryoshkaNum = 0;
    vector<int> ans;

    cin >> n;
    if( n == 0 ){
      break;
    }

    matryoBanpei.h = -1;
    matryoBanpei.r = -1;
    dolls.push_back( matryoBanpei );
    
    InputMatryoshka( dolls, n );

    cin >> m;
    InputMatryoshka( dolls, m );

    sort( dolls.begin(), dolls.end() );
    ans.resize( n+m+1, 0 );

    MaxSubSequenceLength( dolls, ans );

    //output
    for(int i = 0; i < ans.size(); i++){
      maxMatryoshkaNum = max( maxMatryoshkaNum, ans[i] );
    }
    cout << maxMatryoshkaNum << '\n';
  }
  return 0;
}

C++: //Solution for aoj:0157 Russian Dolls
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int, int>P;
const int INF = 1 << 30;

int main(){
	int n, m, a, b;
	P doll[201];
	int dp[201];
	while (cin >> n && n){
		fill(dp, dp + 201, INF);
		for (int i = 0; i < n; i++){
			cin >> a >> b;
			doll[i] = P(a, b);
		}
		cin >> m;
		for (int i = n; i < n + m; i++){
			cin >> a >> b;
			doll[i] = P(a, b);
		}
		sort(doll, doll + n + m);
		for (int i = 0; i < n + m; i++){
			if (doll[i].first == doll[i - 1].first){
				doll[i] = P(0, 0);
			}
		}
		for (int i = 0; i < n + m; i++){
			*lower_bound(dp, dp + n + m, doll[i].second) = doll[i].second;
		}
		cout << lower_bound(dp, dp + n + m, INF) - dp << endl;
	}
}

C++: #include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;

#define loop(i,a,b) for(int i=(a);i<int(b);i++)
#define rep(i,b) loop(i,0,b)
typedef pair<int,int> pii;
int n,m;
pii a[222];
int dp[222];

inline bool le(pii const& t, pii const& u){
    return t.first<u.first && t.second<u.second;
}

int solve(){
    sort(a,a+n+m);
    dp[0]=1;
    for(int i=0;i<n+m;i++){
        for(int j=0;j<i;j++){
            if(le(a[j],a[i])){
                dp[i]=max(dp[i],dp[j]+1);
            }
        }
    }
    int ans=0;
    for(int i=0;i<n+m;i++){
        ans=max(ans,dp[i]);
    }
    return ans;
}

int main(){
    while(cin>>n && n){
        rep(i,n)cin>>a[i].first>>a[i].second;
        cin>>m;
        rep(i,m)cin>>a[i+n].first>>a[i+n].second;
        cout << solve() << endl;
    }
}

C++: // 0157 最長増加部分列
#include <iostream>
#include <algorithm>
#include <map>

#define rep(i, n) for(int i = 0; i < n; i++)

using namespace std;
bool compare_h(pair<int, int> a, pair<int, int> b){
	return a.first < b.first;
}
bool compare_r(pair<int, int> a, pair<int, int> b){
	return a.second < b.second;
}


int main(){
	int n, m;
	while(cin >> n && n){
		int dp[256];
		// high, r
		pair<int, int> dolls[256];
		rep(i, n){
			cin >> dolls[i].first >> dolls[i].second;
		}
		cin >> m;
		rep(i, m){
			cin >> dolls[i+n].first >> dolls[i+n].second;
		}


		// hの最長増加部分列
		// hについてソートしrの最長増加部分列を求める
		int hlis = 0;
		sort(dolls, dolls+n+m, compare_h);
		dp[0] = 1;
		for(int i = 1; i < n+m; i++){
			dp[i] = 1;
			for(int j = 0; j < i; j++){
				if(dolls[j].second < dolls[i].second){
					dp[i] = max(dp[i], dp[j] + 1);
				}
			}
			hlis = max(hlis, dp[i]);
		}					
		
		// rの最長増加部分列
		// rについてソートしhの最長増加部分列を求める
		int rlis = 0;
		sort(dolls, dolls+n+m, compare_r);
		dp[0] = 1;
		for(int i = 1; i < n+m; i++){
			dp[i] = 1;
			for(int j = 0; j < i; j++){
				if(dolls[j].first < dolls[i].first){
					dp[i] = max(dp[i], dp[j] + 1);
				}
			}
			rlis = max(rlis, dp[i]);
		}

		cout << max(rlis, hlis) << endl;
	}

	return 0;
}

C++: #include <iostream>
#include <algorithm>

using namespace std;

const int MAX_SIZE = 1000;
const int N = 100;

main(){
   int n, m, sizeH, sizeR;
   int dp[MAX_SIZE+1][MAX_SIZE+1];
   int dataH[2][N];
   int dataR[2][N];
   while(cin >> n && n){
      sizeH = sizeR = 0;
      for(int i=0;i<n;++i){
         cin >> dataH[0][i] >> dataR[0][i];
         sizeH = max(sizeH, dataH[0][i]);
         sizeR = max(sizeR, dataR[0][i]);
      }
      cin >> m;
      for(int i=0;i<m;++i){
         cin >> dataH[1][i] >> dataR[1][i];
         sizeH = max(sizeH, dataH[1][i]);
         sizeR = max(sizeR, dataR[1][i]);
      }
      fill(dp[0], dp[MAX_SIZE], -1);
      dp[0][0] = 1;
      for(int i=0;i<sizeH;++i){
         for(int j=0;j<sizeR;++j){
            if(dp[i][j] == -1) continue;
            for(int k=0;k<n;++k){
               if(dataH[0][k] > i && dataR[0][k] > j) dp[dataH[0][k]][dataR[0][k]] = dp[i][j] + 1;
            }
            for(int k=0;k<m;++k){
               if(dataH[1][k] > i && dataR[1][k] > j) dp[dataH[1][k]][dataR[1][k]] = dp[i][j] + 1;
            }
         }
      }
      int ans = 0;
      for(int i=0;i<sizeH;++i){
         for(int j=0;j<sizeR;++j){
            ans = max(ans, dp[i][j]);
         }
      }
      cout << ans << endl;
   }
   return 0;
}