#include <bits/stdc++.h>
using namespace std;
string s;
class SegmentTree {
  struct data {
    int ans;
    int opened;
    int closed;
  };

 public:
  data merge(data A, data B) {
    int extra = min(A.opened, B.closed);
    return data{A.ans + B.ans + extra, A.opened + B.opened - extra,
                A.closed + B.closed - extra};
  }
  data leafNodeValue(int index) {
    if (s[index] == '(')
      return data{0, 1, 0};
    else
      return data{0, 0, 1};
  }
  void updateNode(data& node, int& value, int& start, int& end) {}
  void updateLazy(int& child, int& parent) {}
  data outOfRange;
  int defaultLazyValue;
  void setDefaultAndOutOfRange() { outOfRange = {0, 0, 0}; }
  SegmentTree(int n) {
    setDefaultAndOutOfRange();
    size = n;
    tree = new data[n << 3];
    lazy = new int[n << 3];
    build(1, 0, size - 1);
  }
  void update(int start, int end, int value) {
    update(1, 0, size - 1, start, end, value);
  }
  data query(int start, int end) { return query(1, 0, size - 1, start, end); }

 private:
  void build(int node, int start, int end) {
    int into2 = node << 1, mid = (start + end) / 2;
    if (start == end) {
      tree[node] = leafNodeValue(start);
      lazy[node] = defaultLazyValue;
    } else {
      build(into2, start, mid), build(into2 + 1, mid + 1, end);
      lazy[node] = defaultLazyValue;
      tree[node] = merge(tree[into2], tree[into2 + 1]);
    }
  }
  void push(int node, int start, int end) {
    return;
    if (lazy[node] != defaultLazyValue) {
      updateNode(tree[node], lazy[node], start, end);
      if (start != end) {
        updateLazy(lazy[node + node], lazy[node]);
        updateLazy(lazy[node + node + 1], lazy[node]);
      }
      lazy[node] = defaultLazyValue;
    }
  }
  void update(int node, int start, int end, int rangestart, int rangeend,
              int value) {
    return;
    int into2 = node << 1, mid = (start + end) / 2;
    push(node, start, end);
    if (start > end || start > rangeend || end < rangestart) return;
    if (rangestart <= start && end <= rangeend) {
      updateNode(tree[node], value, start, end);
      if (start != end) {
        updateLazy(lazy[into2 + 1], value);
        updateLazy(lazy[into2], value);
      }
      return;
    }
    update(into2, start, mid, rangestart, rangeend, value),
        update(into2 + 1, mid + 1, end, rangestart, rangeend, value);
    tree[node] = merge(tree[into2], tree[into2 + 1]);
  }
  data query(int node, int start, int end, int rangestart, int rangeend) {
    int into2 = node << 1, mid = (start + end) / 2;
    if (start > end || start > rangeend || end < rangestart) return outOfRange;
    push(node, start, end);
    if (rangestart <= start && end <= rangeend) return tree[node];
    return merge(query(into2, start, mid, rangestart, rangeend),
                 query(into2 + 1, mid + 1, end, rangestart, rangeend));
  }
  long long int size;
  data* tree;
  int* lazy;
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(NULL);
  ;
  cin >> s;
  SegmentTree S(s.size());
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int l, r;
    cin >> l >> r;
    cout << 2 * S.query(l - 1, r - 1).ans << endl;
  }
  return 0;
}
