// g++ file.cpp -o test
// ./test

#include <stdio.h>
#include <string>
#include <iostream>
#include <vector> // gotta include vector!!
using namespace std;

// you are given a string of partial game results
// how many possible winners are there?
// ah wait: just compute the number of possible winners at each internal node
// each query just corresponds to updating one path through the tree which isn't too bad

// how do I represent this tree?
// 0, 1, ..., 2^(k+1) - 2
// 0, 1, ..., 2^k - 1 are the original players
// 2^k: 0 vs 1 - in flipped coords: 2^k - 1: 2^(k+1) - 1 vs. 2^(k+1) - 2
// 2^k + 1: 2 vs 3 - in flipped coords: 2^k - 2: 2^(k+1) - 4, 2^(k+1) - 3
// final node in flipped: 1: 2 vs 3
// okay yeah, so in flipped coords (x --> 2^(k+1) - 1 - x), node t is 2t vs 2t+1
// with these coords: 2^k to 2^(k+1) - 1

typedef long long ll;

int main() {
    int k;
    cin >> k;
    string s;
    getline(cin, s);

    // STEP 1: read the string in and compute the initial results
    getline(cin, s);
    int length = (1 << (k+1)) - 1;
    int counts[length];
    // int countscache[length];

    for (int i = 0; i < (1 << k); i++) counts[i] = 1; // original players/leaf nodes

    for (int i = (1 << k); i < length; i++) {
        int iflip = length - i;
        char result = s[i - (1<<k)];
        int leftflip = 2 * iflip;
        int rightflip = 2 * iflip + 1;
        int left = length - leftflip;
        int right = length - rightflip;
        // right has lower numbers than left

        if (result == '0') counts[i] = counts[right]; // careful distinguishing char vs ints here!!!
        else if (result == '1') counts[i] = counts[left];
        else counts[i] = counts[left] + counts[right];
    }

    // for (int i = 0; i < length; i++) countscache[i] = counts[i];

    // for (int i = 0; i < length; i++) cout << counts[i] << " ";
    // cout << endl;

    // STEP 2: handle queries
    int q; cin >> q;
    for (int j = 0; j < q; j++) {
        int p; cin >> p;
        char result; cin >> result;
        s[p-1] = result;
        // vector<int> updates;

        // update the tree according to queries
        int i = p + (1 << k) - 1;
        while (i < length) {
            int iflip = length - i;
            char result = s[i - (1<<k)];
            int leftflip = 2 * iflip;
            int rightflip = 2 * iflip + 1;
            int left = length - leftflip;
            int right = length - rightflip;
            // right has lower numbers than left

            if (result == '0') counts[i] = counts[right];
            else if (result == '1') counts[i] = counts[left];
            else counts[i] = counts[left] + counts[right];

            int childflip = iflip/2;
            i = length - childflip;
        }

        cout << counts[length - 1] << endl;

        // clean up and restore the tree - this may not be necessary actually, I don't think this is the point...
        // for (int i = 0; i < length; i++) cout << counts[i] << " ";
        // cout << endl;
    }

    return 0;
}