Problem:
Iron Bars
A boy PCK had
N
straight iron bars, which were serially indexed. Unfortunately, the first
M
bars (0 ≤
M
≤
N
) among them were bent during transportation. They all suffered a perpendicular bend at one point.
He is planning to make a cube using a set of bars selected using the following rules:
X
bars from bent ones,
Y
bars from straight ones, where
2X + Y = 12
. Any two bars can be jointed only at the apexes of the cube. He wants to count how many types of rectangular parallelepipeds (hereafter RP) he can make using these bars.
Make a program to count out types (different shapes) of RPs that PCK can make using the following information: the number of bars and length of each one, position of the bend, and the number of bars to be used to construct an RP. Note that any two RPs similar in shape are considered identical: namely if the length of three defining sides of two RPs coincide if arranged in increasing/decreasing order (e.g., three sides of RP
i
and
j
are
A_i, B_i, C_i
, and
A_j, B_j
and
C_j
in increasing order, then the relations
A_i = A_j, B_i = B_j
, and
C_i = C_j
hold. Note also that the bars are sufficiently thin to allow you to consider them as idealized lines.
Input
The input is given in the following format.
N
M
X
Y
a_1
a_2
:
a_N
b_1
b_2
:
b_M
The first line provides the total number of iron bars and bent bars, and those straight and bent bars used to construct an RP:
N
(6 ≤
N
≤ 6000),
M
(0 ≤
M
≤
N
),
X
(0 ≤
X
≤ 6), and
Y
(0 ≤
Y
≤ 12). The following relations always hold for them:
2X+Y=12
,
X+Y
≤
N
,
X
≤
M
. Each of the subsequent
N
lines provides the length of the
i
-th bar
a_i
(1 ≤
a_i
≤ 6000) in integers. Furthermore, each of the subsequent
M
lines provides the location at which the
i
-th bent bar suffered a perpendicular bend
b_i
(1 ≤
b_i
≤ 3000) in centimeters from one end of the bar (note: 1 ≤
a_i-b_i
≤ 3000).
Output
Output the number of constructible rectangular parallelepipeds.
Sample Input 1
18 8 3 6
4
3
3
3
3
2
2
2
1
1
1
1
1
2
2
3
3
3
1
1
1
1
1
1
1
1
Sample Output 1
3

Submitted solutions:

code_snippet: // AOJ #379
// Iron Bars 2025.2.9

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

struct FastBitset {
    vector<ull> data;
    int size;
    FastBitset() {}
    FastBitset(int n) : size(n) {
        int blocks = (n + 63) / 64;
        data.assign(blocks, 0ULL);
    }
    void init(int n) {
        size = n;
        int blocks = (n + 63) / 64;
        data.assign(blocks, 0ULL);
    }
    void set(int i) {
        data[i >> 6] |= (1ULL << (i & 63));
    }
    bool test(int i) const {
        return (data[i >> 6] >> (i & 63)) & 1ULL;
    }
    void reset() {
        fill(data.begin(), data.end(), 0ULL);
    }
    void bit_and(const FastBitset &other) {
        int sz = data.size();
        for (int i = 0; i < sz; i++)
            data[i] &= other.data[i];
    }
    FastBitset operator&(const FastBitset &other) const {
        FastBitset ret;
        ret.size = size;
        ret.data.resize(data.size());
        int sz = data.size();
        for (int i = 0; i < sz; i++)
            ret.data[i] = data[i] & other.data[i];
        return ret;
    }
    int popcount() const {
        int cnt = 0;
        for (auto &x : data)
            cnt += __builtin_popcountll(x);
        return cnt;
    }
};
 
struct PairKey { int p, q; };
struct PairKeyHash {
    std::size_t operator()(const PairKey &pk) const {
        return ((size_t)pk.p * 6007ULL) ^ ((size_t)pk.q);
    }
};
struct PairKeyEqual {
    bool operator()(const PairKey &a, const PairKey &b) const {
        return a.p == b.p && a.q == b.q;
    }
};
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M, X, Y;
    cin >> N >> M >> X >> Y;
    vector<int> a(N), b(M);
    for (int i = 0; i < N; i++) cin >> a[i];
    for (int i = 0; i < M; i++) cin >> b[i];
 
    const int MAXLEN = 6000;
    vector<int> straightCount(MAXLEN+1, 0);
    for (int i = M; i < N; i++) straightCount[a[i]]++;
 
    unordered_map<PairKey,int,PairKeyHash,PairKeyEqual> bentMap;
    bentMap.reserve(M*2);
    for (int i = 0; i < M; i++){
        int tot = a[i];
        int bendPos = b[i];
        int seg1 = bendPos, seg2 = tot - bendPos;
        int p = min(seg1, seg2), q = max(seg1, seg2);
        PairKey key { p, q };
        bentMap[key]++;
    }
    auto getBentCount = [&](int p, int q) -> int {
        PairKey key { p, q };
        auto it = bentMap.find(key);
        return (it == bentMap.end()) ? 0 : it->second;
    };
 
    vector<bool> candidateFlag(MAXLEN+1, false);
    for (int d = 1; d <= MAXLEN; d++){
        if(straightCount[d] > 0)
            candidateFlag[d] = true;
    }
    for(auto &entry : bentMap){
        candidateFlag[entry.first.p] = true;
        candidateFlag[entry.first.q] = true;
    }
    vector<int> cand;
    for (int d = 1; d <= MAXLEN; d++){
        if(candidateFlag[d])
            cand.push_back(d);
    }
    sort(cand.begin(), cand.end());
    int n = cand.size();
 
    vector<int> candStraight(n);
    for (int i = 0; i < n; i++){
        candStraight[i] = straightCount[cand[i]];
    }
    vector<int> selfB(n, 0);
    for (int i = 0; i < n; i++){
        selfB[i] = getBentCount(cand[i], cand[i]);
    }
    vector<vector<unsigned char>> bentVal(n);
    for (int i = 0; i < n; i++){
        bentVal[i].resize(n - i - 1, 0);
        for (int j = i + 1; j < n; j++){
            int cnt = getBentCount(cand[i], cand[j]);
            if(cnt > 5) cnt = 5;
            bentVal[i][j - i - 1] = (unsigned char) cnt;
        }
    }
 
    struct Distrib { int x12, x13, x23, r1, r2, r3; };
    vector<Distrib> Dvec;
    for (int x12 = 0; x12 <= X; x12++){
        for (int x13 = 0; x13 <= X - x12; x13++){
            int x23 = X - x12 - x13;
            if(x12 + x13 > 4) continue;
            if(x12 + x23 > 4) continue;
            if(x13 + x23 > 4) continue;
            Distrib d;
            d.x12 = x12; d.x13 = x13; d.x23 = x23;
            d.r1 = 4 - (x12 + x13);
            d.r2 = 4 - (x12 + x23);
            d.r3 = 4 - (x13 + x23);
            Dvec.push_back(d);
        }
    }
 
    int mwords = (n + 63) / 64;
    vector<FastBitset> maskFrom(n + 1, FastBitset(n));
    for (int j = 0; j <= n; j++){
        maskFrom[j].init(n);
        int startBlock = j >> 6, startOffset = j & 63;
        for (int b = startBlock; b < mwords; b++){
            ull blockVal = ~0ULL;
            if(b == startBlock)
                blockVal &= ~((1ULL << startOffset) - 1ULL);
            if(b == mwords - 1){
                int extra = mwords * 64 - n;
                if(extra > 0)
                    blockVal &= ~0ULL >> extra;
            }
            maskFrom[j].data[b] = blockVal;
        }
    }
    vector<FastBitset> maskTo(n + 1, FastBitset(n));
    for (int j = 0; j <= n; j++){
        maskTo[j].init(n);
        for (int b = 0; b < mwords; b++){
            int blockStart = b * 64, blockEnd = min(n, (b + 1) * 64);
            ull bits = 0ULL;
            for (int i = blockStart; i < blockEnd; i++){
                if(i < j)
                    bits |= (1ULL << (i - blockStart));
            }
            maskTo[j].data[b] = bits;
        }
    }
 
    int maxStraightThr = 12;
    vector<FastBitset> straightBS(maxStraightThr + 1, FastBitset(n));
    for (int thr = 0; thr <= maxStraightThr; thr++){
        straightBS[thr].init(n);
        for (int i = 0; i < n; i++){
            if(candStraight[i] >= thr){
                int block = i >> 6;
                int bit = i & 63;
                straightBS[thr].data[block] |= (1ULL << bit);
            }
        }
    }
 
    int maxBentThr = 6;
    vector<vector<FastBitset>> bs(n, vector<FastBitset>(maxBentThr + 1, FastBitset(n)));
    for (int i = 0; i < n; i++){
        for (int t = 0; t <= maxBentThr; t++){
            bs[i][t].init(n);
            for (int j = i + 1; j < n; j++){
                bool ok = (t == 0) ? true : (((int)bentVal[i][j - i - 1]) >= t);
                if(ok){
                    int block = j >> 6;
                    int bit = j & 63;
                    bs[i][t].data[block] |= (1ULL << bit);
                }
            }
        }
    }
    vector<vector<FastBitset>> bentRev(n, vector<FastBitset>(maxBentThr + 1, FastBitset(n)));
    for (int j = 0; j < n; j++){
        for (int t = 0; t <= maxBentThr; t++){
            bentRev[j][t].init(n);
            for (int i = 0; i < j; i++){
                bool ok = (t == 0) ? true : (((int)bentVal[i][j - i - 1]) >= t);
                if(ok){
                    int block = i >> 6;
                    int bit = i & 63;
                    bentRev[j][t].data[block] |= (1ULL << bit);
                }
            }
        }
    }
 
    int dSize = Dvec.size();
    ll ans = 0;
    int totalSubs = 1 << dSize;
    for (int mask = 1; mask < totalSubs; mask++){
        int bits = 0;
        int agg_R1 = 0, agg_R2 = 0, agg_R3 = 0;
        int agg_S12 = 0, agg_S23 = 0;
        int agg_S123 = Y;
        int agg_B12 = 0, agg_B13 = 0, agg_B23 = 0;
        int agg_S_AC = 0, agg_S_AB = 0;
        int agg_S_total = X;
        for (int i = 0; i < dSize; i++){
            if(mask & (1 << i)){
                bits++;
                Distrib d = Dvec[i];
                agg_R1 = max(agg_R1, d.r1);
                agg_R2 = max(agg_R2, d.r2);
                agg_R3 = max(agg_R3, d.r3);
                agg_S12 = max(agg_S12, d.r1 + d.r2);
                agg_S23 = max(agg_S23, d.r2 + d.r3);
                agg_B12 = max(agg_B12, d.x12);
                agg_B13 = max(agg_B13, d.x13);
                agg_B23 = max(agg_B23, d.x23);
                agg_S_AC = max(agg_S_AC, d.x13 + d.x23);
                agg_S_AB = max(agg_S_AB, d.x12 + d.x13);
            }
        }
        if(agg_B12 > 5 || agg_B13 > 5 || agg_B23 > 5 || agg_S_AC > 5 || agg_S_AB > 5)
            continue;
 
        ll fcount = 0;
 
        for (int i = 0; i < n; i++){
            if(candStraight[i] >= agg_S123 && selfB[i] >= agg_S_total)
                fcount++;
        }
 
        for (int i = 0; i < n; i++){
            if(candStraight[i] < agg_S12) continue;
            if(selfB[i] < agg_B12) continue;
            FastBitset bsIntersect = bs[i][agg_S_AC];
            int sz = bsIntersect.data.size();
            for (int b = 0; b < sz; b++){
                bsIntersect.data[b] &= straightBS[agg_R3].data[b];
            }
            bsIntersect.bit_and(maskFrom[i+1]);
            fcount += bsIntersect.popcount();
        }
 
        for (int j = 1; j < n; j++){
            if(candStraight[j] < agg_S23) continue;
            if(selfB[j] < agg_B23) continue;
            FastBitset bsIntersect = bentRev[j][agg_S_AB];
            int sz = bsIntersect.data.size();
            for (int b = 0; b < sz; b++){
                bsIntersect.data[b] &= straightBS[agg_R1].data[b];
                bsIntersect.data[b] &= maskTo[j].data[b];
            }
            fcount += bsIntersect.popcount();
        }
 
        for (int i = 0; i < n; i++){
            if(candStraight[i] < agg_R1) continue;
            FastBitset validJ = bs[i][agg_B12];
            int sz = validJ.data.size();
            for (int b = 0; b < sz; b++){
                validJ.data[b] &= straightBS[agg_R2].data[b];
            }
            validJ.bit_and(maskFrom[i+1]);
            for (int block = 0; block < sz; block++){
                ull bitsVal = validJ.data[block];
                while(bitsVal){
                    int j = (block << 6) | __builtin_ctzll(bitsVal);
                    bitsVal &= bitsVal - 1;
                    FastBitset candK = bs[i][agg_B13];
                    int szK = candK.data.size();
                    for (int b2 = 0; b2 < szK; b2++){
                        candK.data[b2] &= bs[j][agg_B23].data[b2];
                        candK.data[b2] &= straightBS[agg_R3].data[b2];
                    }
                    candK.bit_and(maskFrom[j+1]);
                    fcount += candK.popcount();
                }
            }
        }
 
        int sign = (bits % 2 == 1) ? 1 : -1;
        ans += sign * fcount;
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 1620
memory_kb: 37828
final_rank: 8

code_snippet: #include <iostream>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

int N, A[6009];
int M, B[6009];
vector<int> L1;
vector<pair<int, int>> L2;
int Cnt1[6009];
int Cnt2[6009][6009];
int X;
int Y;
vector<tuple<int, int, int>> Cand[7];

void Initialize() {
	for (int i = 0; i <= 6; i++) {
		for (int j = 0; j <= 6; j++) {
			for (int k = 0; k <= 6; k++) {
				if (i + j + k >= 7) continue;
				if (i + j + k == 6 && !(i == 2 && j == 2 && k == 2)) continue;
				if (i + j + k == 5 && i * j * k == 0) continue;
				Cand[i + j + k].push_back(make_tuple(i, j, k));
			}
		}
	}
}

// =============================================================================== Solve when X=0
long long solve_Subtask1() {
	vector<int> Sum(6009, 0);
	for (int i = 6007; i >= 0; i--) {
		Sum[i] = Sum[i + 1];
		if (Cnt1[i] >= 4) Sum[i] += 1;
	}

	// Counting
	long long Answer = 0;
	for (int i = 0; i <= 6000; i++) {
		for (int j = i; j <= 6000; j++) {
			bool flag = false;
			Cnt1[i] -= 4; Cnt1[j] -= 4;
			if (Cnt1[i] < 0) flag = true;
			if (Cnt1[j] < 0) flag = true;
			int ways = Sum[j + 1];
			if (Cnt1[j] >= 4) ways += 1;
			if (flag == false) Answer += ways;
			Cnt1[i] += 4; Cnt1[j] += 4;
		}
	}
	return Answer;
}

// =============================================================================== Solve when 1<=X<=5
bool helper(int pa, int pb, int pc) {
	for (tuple<int, int, int> v : Cand[X]) {
		Cnt2[pa][pb] -= get<0>(v);
		Cnt2[pa][pc] -= get<1>(v);
		Cnt2[pb][pc] -= get<2>(v);
		Cnt1[pa] -= 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] -= 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] -= 4 - get<1>(v) - get<2>(v);
		bool flag = false;
		if (Cnt2[pa][pb] < 0) flag = true;
		if (Cnt2[pa][pc] < 0) flag = true;
		if (Cnt2[pb][pc] < 0) flag = true;
		if (Cnt1[pa] < 0) flag = true;
		if (Cnt1[pb] < 0) flag = true;
		if (Cnt1[pc] < 0) flag = true;
		Cnt2[pa][pb] += get<0>(v);
		Cnt2[pa][pc] += get<1>(v);
		Cnt2[pb][pc] += get<2>(v);
		Cnt1[pa] += 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] += 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] += 4 - get<1>(v) - get<2>(v);
		if (flag == false) return true;
	}
	return false;
}

long long solve_Subtask2() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L1.size(); i++) {
		for (int j = 0; j < L2.size(); j++) {
			vector<int> vec;
			vec.push_back(L1[i]);
			vec.push_back(L2[j].first);
			vec.push_back(L2[j].second);
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) {
				Answer.push_back(make_tuple(pa, pb, pc));
			}
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

// =============================================================================== Solve when X=6
long long solve_Subtask3() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L2.size(); i++) {
		for (int j = i; j < L2.size(); j++) {
			vector<int> vec;
			if (L2[i].first == L2[j].first) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].second); }
			else if (L2[i].first == L2[j].second) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].first); }
			else if (L2[i].second == L2[j].first) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].second); }
			else if (L2[i].second == L2[j].second) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].first); }
			if (vec.size() == 0) continue;
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) Answer.push_back(make_tuple(pa, pb, pc));
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

int main() {
	// Step 1. Input
	cin >> N >> M >> X >> Y;
	for (int i = 1; i <= N; i++) cin >> A[i];
	for (int i = 1; i <= M; i++) cin >> B[i];
	Initialize();

	// Step 2. Precount
	for (int i = 1; i <= M; i++) {
		int c1 = B[i], c2 = A[i] - B[i];
		if (c1 > c2) swap(c1, c2);
		L2.push_back(make_pair(c1, c2));
		Cnt2[c1][c2] += 1;
	}
	for (int i = M + 1; i <= N; i++) {
		L1.push_back(A[i]);
		Cnt1[A[i]] += 1;
	}
	sort(L1.begin(), L1.end()); L1.erase(unique(L1.begin(), L1.end()), L1.end());
	sort(L2.begin(), L2.end()); L2.erase(unique(L2.begin(), L2.end()), L2.end());

	// Step 3. Output
	if (X == 0) cout << solve_Subtask1() << endl;
	if (X == 1) cout << solve_Subtask2() << endl;
	if (X == 2) cout << solve_Subtask2() << endl;
	if (X == 3) cout << solve_Subtask2() << endl;
	if (X == 4) cout << solve_Subtask2() << endl;
	if (X == 5) cout << solve_Subtask2() << endl;
	if (X == 6) cout << solve_Subtask3() << endl;
	return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 62740
final_rank: 4

code_snippet: #include <iostream>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

int N, A[6009];
int M, B[6009];
vector<int> L1;
vector<pair<int, int>> L2;
int Cnt1[3009];
int Cnt2[3009][3009];
int X;
int Y;
vector<tuple<int, int, int>> Cand[7];

void Initialize() {
	for (int i = 0; i <= 6; i++) {
		for (int j = 0; j <= 6; j++) {
			for (int k = 0; k <= 6; k++) {
				if (i + j + k >= 7) continue;
				if (i + j + k == 6 && !(i == 2 && j == 2 && k == 2)) continue;
				if (i + j + k == 5 && i * j * k == 0) continue;
				Cand[i + j + k].push_back(make_tuple(i, j, k));
			}
		}
	}
}

// =============================================================================== Solve when X=0
long long solve_Subtask1() {
	vector<int> Sum(3009, 0);
	for (int i = 3007; i >= 0; i--) {
		Sum[i] = Sum[i + 1];
		if (Cnt1[i] >= 4) Sum[i] += 1;
	}

	// Counting
	long long Answer = 0;
	for (int i = 0; i <= 3000; i++) {
		for (int j = i; j <= 3000; j++) {
			bool flag = false;
			Cnt1[i] -= 4; Cnt1[j] -= 4;
			if (Cnt1[i] < 0) flag = true;
			if (Cnt1[j] < 0) flag = true;
			int ways = Sum[j + 1];
			if (Cnt1[j] >= 4) ways += 1;
			if (flag == false) Answer += ways;
			Cnt1[i] += 4; Cnt1[j] += 4;
		}
	}
	return Answer;
}

// =============================================================================== Solve when 1<=X<=5
bool helper(int pa, int pb, int pc) {
	for (tuple<int, int, int> v : Cand[X]) {
		Cnt2[pa][pb] -= get<0>(v);
		Cnt2[pa][pc] -= get<1>(v);
		Cnt2[pb][pc] -= get<2>(v);
		Cnt1[pa] -= 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] -= 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] -= 4 - get<1>(v) - get<2>(v);
		bool flag = false;
		if (Cnt2[pa][pb] < 0) flag = true;
		if (Cnt2[pa][pc] < 0) flag = true;
		if (Cnt2[pb][pc] < 0) flag = true;
		if (Cnt1[pa] < 0) flag = true;
		if (Cnt1[pb] < 0) flag = true;
		if (Cnt1[pc] < 0) flag = true;
		Cnt2[pa][pb] += get<0>(v);
		Cnt2[pa][pc] += get<1>(v);
		Cnt2[pb][pc] += get<2>(v);
		Cnt1[pa] += 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] += 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] += 4 - get<1>(v) - get<2>(v);
		if (flag == false) return true;
	}
	return false;
}

long long solve_Subtask2() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L1.size(); i++) {
		for (int j = 0; j < L2.size(); j++) {
			vector<int> vec;
			vec.push_back(L1[i]);
			vec.push_back(L2[j].first);
			vec.push_back(L2[j].second);
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) {
				Answer.push_back(make_tuple(pa, pb, pc));
			}
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

// =============================================================================== Solve when X=6
long long solve_Subtask3() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L2.size(); i++) {
		for (int j = i; j < L2.size(); j++) {
			vector<int> vec;
			if (L2[i].first == L2[j].first) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].second); }
			else if (L2[i].first == L2[j].second) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].first); }
			else if (L2[i].second == L2[j].first) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].second); }
			else if (L2[i].second == L2[j].second) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].first); }
			if (vec.size() == 0) continue;
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) Answer.push_back(make_tuple(pa, pb, pc));
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

int main() {
	// Step 1. Input
	cin >> N >> M >> X >> Y;
	for (int i = 1; i <= N; i++) cin >> A[i];
	for (int i = 1; i <= M; i++) cin >> B[i];
	Initialize();

	// Step 2. Precount
	for (int i = 1; i <= M; i++) {
		int c1 = B[i], c2 = A[i] - B[i];
		if (c1 > c2) swap(c1, c2);
		L2.push_back(make_pair(c1, c2));
		Cnt2[c1][c2] += 1;
	}
	for (int i = M + 1; i <= N; i++) {
		L1.push_back(A[i]);
		Cnt1[A[i]] += 1;
	}
	sort(L1.begin(), L1.end()); L1.erase(unique(L1.begin(), L1.end()), L1.end());
	sort(L2.begin(), L2.end()); L2.erase(unique(L2.begin(), L2.end()), L2.end());

	// Step 3. Output
	if (X == 0) cout << solve_Subtask1() << endl;
	if (X == 1) cout << solve_Subtask2() << endl;
	if (X == 2) cout << solve_Subtask2() << endl;
	if (X == 3) cout << solve_Subtask2() << endl;
	if (X == 4) cout << solve_Subtask2() << endl;
	if (X == 5) cout << solve_Subtask2() << endl;
	if (X == 6) cout << solve_Subtask3() << endl;
	return 0;
}
accuracy: 0.8478260869565217
time_ms: 10
memory_kb: 3732
final_rank: 11

code_snippet: #include <iostream>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

int N, A[6009];
int M, B[6009];
vector<int> L1;
vector<pair<int, int>> L2;
int Cnt1[3009];
int Cnt2[3009][3009];
int X;
int Y;
vector<tuple<int, int, int>> Cand[7];

void Initialize() {
	for (int i = 0; i <= 6; i++) {
		for (int j = 0; j <= 6; j++) {
			for (int k = 0; k <= 6; k++) {
				if (i + j + k >= 7) continue;
				if (i + j + k == 6 && !(i == 2 && j == 2 && k == 2)) continue;
				if (i + j + k == 5 && i * j * k == 0) continue;
				Cand[i + j + k].push_back(make_tuple(i, j, k));
			}
		}
	}
}

// =============================================================================== Solve when X=0
long long solve_Subtask1() {
	vector<int> Sum(3009, 0);
	for (int i = 3007; i >= 0; i--) {
		Sum[i] = Sum[i + 1];
		if (Cnt1[i] >= 4) Sum[i] += 1;
	}

	// Counting
	long long Answer = 0;
	for (int i = 0; i <= 3000; i++) {
		for (int j = i; j <= 3000; j++) {
			bool flag = false;
			Cnt1[i] -= 4; Cnt1[j] -= 4;
			if (Cnt1[i] < 0) flag = true;
			if (Cnt1[j] < 0) flag = true;
			int ways = Sum[j + 1];
			if (Cnt1[j] >= 4) ways += 1;
			if (flag == false) Answer += ways;
			Cnt1[i] += 4; Cnt1[j] += 4;
		}
	}
	return Answer;
}

// =============================================================================== Solve when 1<=X<=5
bool helper(int pa, int pb, int pc) {
	for (tuple<int, int, int> v : Cand[X]) {
		Cnt2[pa][pb] -= get<0>(v);
		Cnt2[pa][pc] -= get<1>(v);
		Cnt2[pb][pc] -= get<2>(v);
		Cnt1[pa] -= 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] -= 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] -= 4 - get<1>(v) - get<2>(v);
		bool flag = false;
		if (Cnt2[pa][pb] < 0) flag = true;
		if (Cnt2[pa][pc] < 0) flag = true;
		if (Cnt2[pb][pc] < 0) flag = true;
		if (Cnt1[pa] < 0) flag = true;
		if (Cnt1[pb] < 0) flag = true;
		if (Cnt1[pc] < 0) flag = true;
		Cnt2[pa][pb] += get<0>(v);
		Cnt2[pa][pc] += get<1>(v);
		Cnt2[pb][pc] += get<2>(v);
		Cnt1[pa] += 4 - get<0>(v) - get<1>(v);
		Cnt1[pb] += 4 - get<0>(v) - get<2>(v);
		Cnt1[pc] += 4 - get<1>(v) - get<2>(v);
		if (flag == false) return true;
	}
	return false;
}

long long solve_Subtask2() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L1.size(); i++) {
		for (int j = 0; j < L2.size(); j++) {
			vector<int> vec;
			vec.push_back(L1[i]);
			vec.push_back(L2[j].first);
			vec.push_back(L2[j].second);
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) {
				Answer.push_back(make_tuple(pa, pb, pc));
			}
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

// =============================================================================== Solve when X=6
long long solve_Subtask3() {
	long long ways = 0;
	vector<tuple<int, int, int>> Answer;
	for (int i = 0; i < L2.size(); i++) {
		for (int j = i + 1; j < L2.size(); j++) {
			vector<int> vec;
			if (L2[i].first == L2[j].first) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].second); }
			else if (L2[i].first == L2[j].second) { vec.push_back(L2[i].first); vec.push_back(L2[i].second); vec.push_back(L2[j].first); }
			else if (L2[i].second == L2[j].first) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].second); }
			else if (L2[i].second == L2[j].second) { vec.push_back(L2[i].second); vec.push_back(L2[i].first); vec.push_back(L2[j].first); }
			if (vec.size() == 0) continue;
			sort(vec.begin(), vec.end());
			int pa = vec[0], pb = vec[1], pc = vec[2];
			if (helper(pa, pb, pc) == true) Answer.push_back(make_tuple(pa, pb, pc));
		}
	}
	sort(Answer.begin(), Answer.end());
	Answer.erase(unique(Answer.begin(), Answer.end()), Answer.end());
	return (long long)Answer.size();
}

int main() {
	// Step 1. Input
	cin >> N >> M >> X >> Y;
	for (int i = 1; i <= N; i++) cin >> A[i];
	for (int i = 1; i <= M; i++) cin >> B[i];
	Initialize();

	// Step 2. Precount
	for (int i = 1; i <= M; i++) {
		int c1 = B[i], c2 = A[i] - B[i];
		if (c1 > c2) swap(c1, c2);
		L2.push_back(make_pair(c1, c2));
		Cnt2[c1][c2] += 1;
	}
	for (int i = M + 1; i <= N; i++) {
		L1.push_back(A[i]);
		Cnt1[A[i]] += 1;
	}
	sort(L1.begin(), L1.end()); L1.erase(unique(L1.begin(), L1.end()), L1.end());
	sort(L2.begin(), L2.end()); L2.erase(unique(L2.begin(), L2.end()), L2.end());

	// Step 3. Output
	if (X == 0) cout << solve_Subtask1() << endl;
	if (X == 1) cout << solve_Subtask2() << endl;
	if (X == 2) cout << solve_Subtask2() << endl;
	if (X == 3) cout << solve_Subtask2() << endl;
	if (X == 4) cout << solve_Subtask2() << endl;
	if (X == 5) cout << solve_Subtask2() << endl;
	if (X == 6) cout << solve_Subtask3() << endl;
	return 0;
}
accuracy: 0.17391304347826086
time_ms: 10
memory_kb: 3380
final_rank: 12

code_snippet: #include <tuple>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
bool flag[7][7][7][7][7][7];
int main() {
	int N, M, X, Y;
	cin >> N >> M >> X >> Y;
	vector<int> A(N), B(M);
	for (int i = 0; i < N; ++i) {
		cin >> A[i];
	}
	for (int i = 0; i < M; ++i) {
		cin >> B[i];
	}
	if (X == 0) {
		int maxlen = *max_element(A.begin(), A.end());
		vector<int> ca(maxlen + 1);
		for (int i = M; i < N; ++i) {
			++ca[A[i]];
		}
		long long ans = 0;
		for (int i = 1; i <= maxlen; ++i) {
			for (int j = 1; j <= maxlen; ++j) {
				if (i != j && ca[i] >= 8 && ca[j] >= 4) {
					++ans;
				}
			}
		}
		for (int i = 1; i <= maxlen; ++i) {
			if (ca[i] >= 12) {
				++ans;
			}
		}
		int fourcnt = 0;
		for (int i = 1; i <= maxlen; ++i) {
			if (ca[i] >= 4) {
				++fourcnt;
			}
		}
		ans += 1LL * fourcnt * (fourcnt - 1) * (fourcnt - 2) / 6;
		cout << ans << endl;
		return 0;
	}
	else {
		for (int x = 0; x <= 4; ++x) {
			for (int y = 0; y <= 4; ++y) {
				for (int z = 0; z <= 4; ++z) {
					for (int xy = 0; xy <= 4; ++xy) {
						for (int xz = 0; xz <= 4; ++xz) {
							for (int yz = 0; yz <= 4; ++yz) {
								for (int i = 0; i <= xy; ++i) {
									for (int j = 0; j <= xz; ++j) {
										for (int k = 0; k <= yz; ++k) {
											if (i + j + k != X) continue;
											int rx = 4 - i - j, ry = 4 - i - k, rz = 4 - j - k;
											if (rx >= 0 && ry >= 0 && rz >= 0 && rx <= x && ry <= y && rz <= z) {
												flag[x][y][z][xy][xz][yz] = true;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		int maxlen = 0;
		for (int i = 0; i < M; ++i) {
			if (B[i] > A[i] - B[i]) {
				B[i] = A[i] - B[i];
			}
			maxlen = max(maxlen, A[i] - B[i]);
		}
		for (int i = M; i < N; ++i) {
			maxlen = max(maxlen, A[i]);
		}
		vector<vector<int> > tbl(maxlen + 1, vector<int>(maxlen + 1));
		for (int i = 0; i < M; ++i) {
			++tbl[B[i]][A[i] - B[i]];
		}
		vector<int> ca(maxlen + 1);
		for (int i = M; i < N; ++i) {
			if (A[i] <= maxlen) {
				++ca[A[i]];
			}
		}
		// count (A, B, C) where A != B, B != C and C != A
		vector<tuple<short, short, short> > g;
		for (int i = 0; i < M; ++i) {
			if (B[i] == A[i] - B[i]) continue;
			for (int j = 1; j <= maxlen; ++j) {
				if (B[i] != j && A[i] - B[i] != j) {
					vector<int> arr = { B[i], A[i] - B[i], j };
					if (arr[0] > arr[1]) swap(arr[0], arr[1]);
					if (arr[0] > arr[2]) swap(arr[0], arr[2]);
					if (arr[1] > arr[2]) swap(arr[1], arr[2]);
					g.push_back(make_tuple(arr[0], arr[1], arr[2]));
				}
			}
		}
		sort(g.begin(), g.end());
		g.erase(unique(g.begin(), g.end()), g.end());
		int ans = 0;
		for (tuple<short, short, short> i : g) {
			int x = get<0>(i), y = get<1>(i), z = get<2>(i);
			if (flag[min(ca[x], 4)][min(ca[y], 4)][min(ca[z], 4)][min(tbl[x][y], 4)][min(tbl[x][z], 4)][min(tbl[y][z], 4)]) {
				++ans;
			}
		}
		// count (A, A, B) where A != B
		for (int i = 1; i <= maxlen; ++i) {
			for (int j = 1; j <= maxlen; ++j) {
				if (i == j) continue;
				int ct = min(tbl[min(i, j)][max(i, j)], 4);
				for (int k = 0; k <= ct && k <= X; ++k) {
					int ra = 8 - k, rb = 4 - k;
					if (tbl[i][i] < X - k || ra < 2 * (X - k)) continue;
					ra -= 2 * (X - k);
					if (ca[i] >= ra && ca[j] >= rb) {
						++ans;
						break;
					}
				}
			}
		}
		// count (A, A, A)
		for (int i = 1; i <= maxlen; ++i) {
			if (tbl[i][i] >= X && ca[i] >= Y) {
				++ans;
			}
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 1410
memory_kb: 199268
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 6005

struct Info{

	int small,large;
};
int N,M,X,Y;
int input[SIZE];
int num_A[SIZE],num_B[3005][SIZE];
Info info[SIZE];
map<ll,bool> MAP;



int main(){

	scanf("%d %d %d %d",&N,&M,&X,&Y);

	int minimum = BIG_NUM,maximum = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d",&input[i]);
		maximum = max(maximum,input[i]);
	}

	for(int i = 0; i <= maximum; i++){

		num_A[i] = 0;
	}
	for(int i = 0; i <= (maximum+1)/2; i++){
		for(int k = 0; k <= maximum; k++){
			num_B[i][k] = 0;
		}
	}

	int tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&tmp);
		num_B[min(tmp,input[i]-tmp)][max(tmp,input[i]-tmp)]++;
		minimum = min(minimum,min(tmp,input[i]-tmp));

		info[i].small = min(tmp,input[i]-tmp);
		info[i].large = max(tmp,input[i]-tmp);
	}
	for(int i = M; i < N; i++){

		num_A[input[i]]++;
		minimum = min(minimum,input[i]);
	}

	//直方体
	ll ans = 0;
	for(int len = minimum; len <= maximum; len++){

		if(X == 0){

			if(num_A[len] >= 12)ans++;

		}else{
			if(len > (maximum+1)/2)break;
			if(num_A[len] >= Y && num_B[len][len] >= X)ans++;
		}
	}

	//2辺が同じ
	for(int p = minimum; p <= maximum; p++){
		for(int q = minimum; q <= maximum; q++){
			if(q == p)continue;

			//p8辺,q4辺
			if(X == 0){ //全てまっすぐな棒

				if(num_A[p] >= 8 && num_A[q] >= 4){

					ans++;
				}

			}else{

				if(p > (maximum+1)/2)break;

				for(int pp = 0; pp <= X; pp++){ //折れ曲がり辺はppまたはpq

					if(num_B[p][p] < pp)continue;

					int pq = X-pp;

					if(num_B[min(p,q)][max(p,q)] < pq)continue;

					int num_p = 2*pp+pq;
					int num_q = pq;

					if(num_p > 8 || num_q > 4)continue;

					int rest_p = 8-num_p;
					int rest_q = 4-num_q;

					if(num_A[p] >= rest_p && num_A[q] >= rest_q){
						ans++;
						break; //2回以上計上しないようにする
					}
				}
			}
		}
	}

	//3辺異なる
	if(X == 0){

		ll num = 0;

		for(int i = minimum; i <= maximum; i++){
			if(num_A[i] >= 4)num++;
		}

		ans += ((num)*(num-1)*(num-2))/6;

	}else{

		int work[3];

		for(int i = 0; i < M; i++){
			if(info[i].small == info[i].large)continue;

			for(int p = minimum; p <= maximum; p++){
				if(p == info[i].small || p == info[i].large)continue;

				work[0] = info[i].small;
				work[1] = info[i].large;
				work[2] = p;
				sort(work,work+3);

				ll tmp_code = work[0]*1000000000+work[1]*10000+work[2];

				auto at = MAP.find(tmp_code);
				if(at != MAP.end())continue;

				bool FLG = false;

				//work[0]4本、work[1]4本,work[2]4本
				for(int a = 0; a <= min(4,X); a++){ //work[0]&work[1]
					if(num_B[work[0]][work[1]] < a)continue;
					for(int b = 0; b <= min(4,X); b++){ //work[0]&work[2]
						if(b+a > min(4,X))break;
						if(num_B[work[0]][work[2]] < b)continue;
						int c = X-(a+b); //work[1]&work[2]
						if(num_B[work[1]][work[2]] < c)continue;

						int rest_0 = 4-(a+b);
						if(rest_0 < 0)continue;

						int rest_1 = 4-(a+c);
						if(rest_1 < 0)continue;

						int rest_2 = 4-(b+c);
						if(rest_2 < 0)continue;

						if(num_A[work[0]] >= rest_0 && num_A[work[1]] >= rest_1 &&
								num_A[work[2]] >= rest_2){
							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(FLG){
					ans++;
					MAP[tmp_code] = true;
				}
			}
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 73616
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 6005

struct Info{

	int small,large;
};
int N,M,X,Y;
int input[SIZE];
int num_A[SIZE],num_B[3005][SIZE];
Info info[SIZE];
map<ll,bool> MAP;



int main(){

	scanf("%d %d %d %d",&N,&M,&X,&Y);

	int minimum = BIG_NUM,maximum = -BIG_NUM;

	for(int i = 0; i < N; i++){

		scanf("%d",&input[i]);
		maximum = max(maximum,input[i]);
	}

	for(int i = 0; i <= maximum; i++){

		num_A[i] = 0;
	}
	for(int i = 0; i <= (maximum+1)/2; i++){
		for(int k = 0; k <= maximum; k++){
			num_B[i][k] = 0;
		}
	}

	int tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&tmp);
		num_B[min(tmp,input[i]-tmp)][max(tmp,input[i]-tmp)]++;
		minimum = min(minimum,min(tmp,input[i]-tmp));

		info[i].small = min(tmp,input[i]-tmp);
		info[i].large = max(tmp,input[i]-tmp);
	}
	for(int i = M; i < N; i++){

		num_A[input[i]]++;
		minimum = min(minimum,input[i]);
	}

	//直方体
	ll ans = 0;
	for(int len = minimum; len <= maximum; len++){

		if(X == 0){

			if(num_A[len] >= 12)ans++;

		}else{
			if(len > (maximum+1)/2)break;
			if(num_A[len] >= Y && num_B[len][len] >= X)ans++;
		}
	}

	//printf("直方体:ans:%lld\n",ans);

	//2辺が同じ
	for(int p = minimum; p <= maximum; p++){
		for(int q = minimum; q <= maximum; q++){
			if(q == p)continue;

			//p8辺,q4辺
			if(X == 0){ //全てまっすぐな棒

				if(num_A[p] >= 8 && num_A[q] >= 4){

					ans++;
				}

			}else{

				if(p > (maximum+1)/2)break;

				for(int pp = 0; pp <= X; pp++){ //折れ曲がり辺はppまたはpq

					if(num_B[p][p] < pp)continue;

					int pq = X-pp;

					if(num_B[min(p,q)][max(p,q)] < pq)continue;

					int num_p = 2*pp+pq;
					int num_q = pq;

					if(num_p > 8 || num_q > 4)continue;

					int rest_p = 8-num_p;
					int rest_q = 4-num_q;

					if(num_A[p] >= rest_p && num_A[q] >= rest_q){
						ans++;
						break; //2回以上計上しないようにする
					}
				}
			}
		}
	}

	//printf("2片々:ans:%lld\n",ans);

	//3辺異なる
	if(X == 0){

		ll num = 0;

		for(int i = minimum; i <= maximum; i++){
			if(num_A[i] >= 4)num++;
		}

		ans += ((num)*(num-1)*(num-2))/6;

	}else{

		int work[3];

		for(int i = 0; i < M; i++){
			if(info[i].small == info[i].large)continue;

			for(int p = minimum; p <= maximum; p++){
				if(p == info[i].small || p == info[i].large)continue;

				work[0] = info[i].small;
				work[1] = info[i].large;
				work[2] = p;
				sort(work,work+3);

				ll tmp_code = work[0]*1000000000+work[1]*10000+work[2];

				auto at = MAP.find(tmp_code);
				if(at != MAP.end())continue;

				bool FLG = false;

				//work[0]4本、work[1]4本,work[2]4本
				for(int a = 0; a <= min(4,X); a++){ //work[0]&work[1]
					if(num_B[work[0]][work[1]] < a)continue;
					for(int b = 0; b <= min(4,X); b++){ //work[0]&work[2]
						if(b+a > min(4,X))break;
						if(num_B[work[0]][work[2]] < b)continue;
						int c = X-(a+b); //work[1]&work[2]
						if(num_B[work[1]][work[2]] < c)continue;

						int rest_0 = 4-(a+b);
						if(rest_0 < 0)continue;

						int rest_1 = 4-(a+c);
						if(rest_1 < 0)continue;

						int rest_2 = 4-(b+c);
						if(rest_2 < 0)continue;

						if(num_A[work[0]] >= rest_0 && num_A[work[1]] >= rest_1 &&
								num_A[work[2]] >= rest_2){
							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(FLG){
					ans++;
					MAP[tmp_code] = true;
					//printf("文字:%s\n",tmp_str.c_str());
				}
			}
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 73628
final_rank: 3

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

int main() {
    int n, m, x, y;
    cin >> n >> m >> x >> y;
    vector<int> A(n), B(m);
    for (auto &&i : A) scanf("%d", &i);
    for (auto &&i : B) scanf("%d", &i);
    int M = 6000;
    vector<int> cnt(M+1);
    vector<vector<int>> cntl(M+1, vector<int>(M+1, 0));
    for (int i = 0; i < n; ++i) {
        if(i < m){
            if(A[i] != B[i]*2) cntl[B[i]][A[i]-B[i]]++;
            cntl[A[i]-B[i]][B[i]]++;
        }else {
            cnt[A[i]]++;
        }
    }
    ll ans = 0;
    for (int i = 1; i <= M; ++i) { // (i, i, i)
        if(cnt[i] >= y && cntl[i][i] >= x) ans++;
    }
    for (int i = 1; i <= M; ++i) {
        for (int j = 1; j <= M; ++j) { // (i, i, j)
            if(i == j) continue;
            int ok = 0;
            for (int k = max(0, x-4); k <= min(x, 8-x); ++k) {
                if(cntl[i][i] >= k && cntl[i][j] >= x-k && cnt[i] >= 8-x-k && cnt[j] >= 4-x+k){
                    ok = 1;
                    break;
                }
            }
            ans += ok;
        }
    }
    if(x == 0){
        ll c = 0;
        for (int i = 1; i <= M; ++i) c += cnt[i] >= 4;
        cout << ans + c*(c-1)*(c-2)/6 << "\n";
        return 0;
    }
    set<ll> v;
    for (int i = 0; i < m; ++i) {
        if(B[i]*2 == A[i]) continue;
        int a = B[i], b = A[i]-B[i];
        for (int c = 1; c <= M; ++c) { // (a, b-a, j)
            if(a == c || b == c) continue;
            for (int p = max(1, x-4); p <= min(4, x); ++p) {
                for (int q = max(0, x-4); p+q <= min(4, x); ++q) {
                    if(cntl[a][b] >= p && cntl[b][c] >= q && cntl[c][a] >= x-p-q && cnt[a] >= 4-x+q && cnt[b] >= 4-p-q && cnt[c] >= 4-x+p){
                        int aa = min({a, b, c}), cc = max({a, b, c}), bb = a+b+c-aa-cc;
                        v.emplace(aa+bb*10000LL+cc*100000000LL);
                    }
                }
            }
        }
    }
    cout << ans + v.size() << "\n";
    return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 144580
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

int main() {
    int n, m, x, y;
    cin >> n >> m >> x >> y;
    vector<int> A(n), B(m);
    for (auto &&i : A) scanf("%d", &i);
    for (auto &&i : B) scanf("%d", &i);
    int M = 6000;
    vector<int> cnt(M+1);
    vector<vector<int>> cntl(M+1, vector<int>(M+1, 0));
    for (int i = 0; i < n; ++i) {
        if(i < m){
            cntl[B[i]][A[i]-B[i]]++;
            cntl[A[i]-B[i]][B[i]]++;
        }else {
            cnt[A[i]]++;
        }
    }
    ll ans = 0;
    for (int i = 1; i <= M; ++i) { // (i, i, i)
        if(cnt[i] >= y && cntl[i][i] >= x) ans++;
    }
    for (int i = 1; i <= M; ++i) {
        for (int j = 1; j <= M; ++j) { // (i, i, j)
            if(i == j) continue;
            int ok = 0;
            for (int k = max(0, x-4); k <= min(x, 8-x); ++k) {
                if(cntl[i][i] >= k && cntl[i][j] >= x-k && cnt[i] >= 8-x-k && cnt[j] >= 4-x+k){
                    ok = 1;
                    break;
                }
            }
            ans += ok;
        }
    }
    if(x == 0){
        ll c = 0;
        for (int i = 1; i <= M; ++i) c += cnt[i] >= 4;
        cout << ans + c*(c-1)*(c-2)/6 << "\n";
        return 0;
    }
    set<ll> v;
    for (int i = 0; i < m; ++i) {
        if(B[i]*2 == A[i]) continue;
        int a = B[i], b = A[i]-B[i];
        for (int c = 1; c <= M; ++c) { // (a, b-a, j)
            if(a == c || b == c) continue;
            for (int p = max(1, x-4); p <= min(4, x); ++p) {
                for (int q = max(0, x-4); p+q <= min(4, x); ++q) {
                    if(cntl[a][b] >= p && cntl[b][c] >= q && cntl[c][a] >= x-p-q && cnt[a] >= 4-x+q && cnt[b] >= 4-p-q && cnt[c] >= 4-x+p){
                        int aa = min({a, b, c}), cc = max({a, b, c}), bb = a+b+c-aa-cc;
                        v.emplace(aa+bb*10000LL+cc*100000000LL);
                    }
                }
            }
        }
    }
    cout << ans + v.size() << "\n";
    return 0;
}
accuracy: 0.021739130434782608
time_ms: 120
memory_kb: 144076
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;

int N, M, X, Y;
vector<int> A, B;
int D[6001], E[6001][6001];

int combination(auto n, auto r) {
  if(n < r) return 0;
  auto res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

int straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i) ++twelve;
    if( 8 <= i) ++eight;
    if( 4 <= i) ++four;
  }
  return combination(four, 3) + combination(eight, 1) * combination(four - 1, 1) + combination(twelve, 1);
}

vector<vector<int>> split() {
  static vector<vector<int>> memo;
  if(!memo.empty()) return memo;
  vector<vector<int>> res;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) res.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo = res;
}

bool cube(auto x) {
  if(E[x][x] < X) return false;
  if(2 * X + D[x] < 12) return false;
  return true;
}

bool cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return false;
  if(2 * E[x][x] + E[x][y] + D[x] < 8) return false;
  if(E[x][y] + D[y] < 4) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 < 2 * i + j) continue;
    if(4 < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return true;
  }
  return false;
}

bool cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return false;
  if(E[x][y] + D[x] < 4) return false;
  if(E[x][y] + 2 * E[y][y] + D[y] < 8) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 < i) continue;
    if(8 < i + 2 * j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return true;
  }
  return false;
}

bool cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return false;
  if(E[x][y] + E[x][z] + D[x] < 4) return false;
  if(E[x][z] + E[y][z] + D[z] < 4) return false;
  if(E[x][y] + E[y][z] + D[y] < 4) return false;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 < a || 4 < b || 4 < c) continue;
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return true;
  }
  return false;
}

int solve() {
  auto res = 0;
  set<long long> used;
  auto memo = [](const auto& L) {return L[0] + 1e4*L[1] + 1e8*L[2];};
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    bool ok;
    if(L[0] == L[2])      ok = cube(L[0]);
    else if(L[0] == L[1]) ok = cuboidA(L[0], L[2]);
    else if(L[1] == L[2]) ok = cuboidB(L[0], L[1]);
    else                  ok = cuboidC(L[0], L[1], L[2]);

    if(!ok) continue;
    if(used.count(memo(L))) continue;
    used.emplace(memo(L));
    ++res;
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 1
time_ms: 670
memory_kb: 9616
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

int combination(auto n, auto r) {
  if(n < r) return 0;
  auto res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

int straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i) ++twelve;
    if( 8 <= i) ++eight;
    if( 4 <= i) ++four;
  }
  return combination(four, 3) + combination(eight, 1) * combination(four - 1, 1) + combination(twelve, 1);
}

vector<vector<int>> split() {
  static vector<vector<int>> memo;
  if(!memo.empty()) return memo;
  vector<vector<int>> res;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) res.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo = res;
}

bool cube(auto x) {
  if(E[x][x] < X) return false;
  if(2 * X + D[x] < 12) return false;
  return true;
}

bool cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return false;
  if(2 * E[x][x] + E[x][y] + D[x] < 8) return false;
  if(E[x][y] + D[y] < 4) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 < 2 * i + j) continue;
    if(4 < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return true;
  }
  return false;
}

bool cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return false;
  if(E[x][y] + D[x] < 4) return false;
  if(E[x][y] + 2 * E[y][y] + D[y] < 8) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 < i) continue;
    if(8 < i + 2 * j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return true;
  }
  return false;
}

bool cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return false;
  if(E[x][y] + E[x][z] + D[x] < 4) return false;
  if(E[x][z] + E[y][z] + D[z] < 4) return false;
  if(E[x][y] + E[y][z] + D[y] < 4) return false;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 < a || 4 < b || 4 < c) continue;
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return true;
  }
  return false;
}

int solve() {
  auto res = 0;
  set<long long> used;
  auto memo = [](const auto& L) {return L[0] + 1e4*L[1] + 1e8*L[2];};
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    bool ok;
    if(L[0] == L[2])      ok = cube(L[0]);
    else if(L[0] == L[1]) ok = cuboidA(L[0], L[2]);
    else if(L[1] == L[2]) ok = cuboidB(L[0], L[1]);
    else                  ok = cuboidC(L[0], L[1], L[2]);

    if(!ok) continue;
    if(used.count(memo(L))) continue;
    used.emplace(memo(L));
    ++res;
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 1
time_ms: 760
memory_kb: 144372
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i) ++twelve;
    if( 8 <= i) ++eight;
    if( 4 <= i) ++four;
  }
  return combination(four, 3) + combination(eight, 1) * combination(four - 1, 1) + combination(twelve, 1);
}

vector<vector<int>> split() {
  static vector<vector<int>> memo;
  if(!memo.empty()) return memo;
  vector<vector<int>> res;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) res.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo = res;
}

bool cube(auto x) {
  if(E[x][x] < X) return false;
  if(2 * X + D[x] < 12) return false;
  return true;
}

bool cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return false;
  if(2 * E[x][x] + E[x][y] + D[x] < 8) return false;
  if(E[x][y] + D[y] < 4) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 < 2 * i + j) continue;
    if(4 < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return true;
  }
  return false;
}

bool cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return false;
  if(E[x][y] + D[x] < 4) return false;
  if(E[x][y] + 2 * E[y][y] + D[y] < 8) return false;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 < i) continue;
    if(8 < i + 2 * j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return true;
  }
  return false;
}

bool cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return false;
  if(E[x][y] + E[x][z] + D[x] < 4) return false;
  if(E[x][z] + E[y][z] + D[z] < 4) return false;
  if(E[x][y] + E[y][z] + D[y] < 4) return false;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 < a || 4 < b || 4 < c) continue;
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return true;
  }
  return false;
}

LL solve() {
  auto res = 0;
  set<LL> used;
  auto memo = [](const auto& L) {return L[0] + 1e4*L[1] + 1e8*L[2];};
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    bool ok;
    if(L[0] == L[2])      ok = cube(L[0]);
    else if(L[0] == L[1]) ok = cuboidA(L[0], L[2]);
    else if(L[1] == L[2]) ok = cuboidB(L[0], L[1]);
    else                  ok = cuboidC(L[0], L[1], L[2]);

    if(!ok) continue;
    if(used.count(memo(L))) continue;
    used.emplace(memo(L));
    ++res;
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 1
time_ms: 720
memory_kb: 144284
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i) ++twelve;
    if( 8 <= i) ++eight;
    if( 4 <= i) ++four;
  }
  return combination(four, 3) + combination(eight, 1) * combination(four - 1, 1) + combination(twelve, 1);
}

vector<vector<int>> split(auto x) {
  vector<vector<int>> res;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) res.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(x, 0);
  return res;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * X + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split(X)) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 < a || 4 < b || 4 < c) continue;
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[2])      res += cube(L[0]);
    else if(L[0] == L[1]) res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2]) res += cuboidB(L[0], L[1]);
    else                  res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.17391304347826086
time_ms: 50
memory_kb: 145936
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i) ++twelve;
    if( 8 <= i) ++eight;
    if( 4 <= i) ++four;
  }
  return combination(four, 3) + combination(eight, 1) * combination(four - 1, 1) + combination(twelve, 1);
}

vector<vector<int>> split(auto x) {
  vector<vector<int>> res;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) res.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(x, 0);
  return res;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * X + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split(X)) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.17391304347826086
time_ms: 60
memory_kb: 145960
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  assert(false);
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i)     ++twelve;
    else if(8 <= i) ++eight;
    else if(4 <= i) ++four;
  }
  return combination(twelve, 1)
         + combination(eight, 1) * combination(four, 1) + combination(twelve, 1) * combination(four, 1) + 2 * combination(twelve, 1) * combination(eight, 1)
         + combination(four, 3) + combination(twelve, 1) * combination(four, 2) + combination(eight, 1) * combination(four, 2) + combination(twelve, 2) * combination(four, 1) + combination(eight, 2) * combination(four, 1) + combination(twelve, 1) * combination(eight, 1) * combination(four, 1) + combination(twelve, 3);
}

vector<vector<int>> memo;
vector<vector<int>> split() {
  if(!memo.empty()) return memo;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) memo.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * X + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.15217391304347827
time_ms: 50
memory_kb: 145908
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i)     ++twelve;
    else if(8 <= i) ++eight;
    else if(4 <= i) ++four;
  }
  return combination(twelve, 1)
         + combination(eight, 1) * combination(four, 1) + combination(twelve, 1) * combination(four, 1) + 2 * combination(twelve, 1) * combination(eight, 1)
         + combination(four, 3) + combination(twelve, 1) * combination(four, 2) + combination(eight, 1) * combination(four, 2) + combination(twelve, 2) * combination(four, 1) + combination(eight, 2) * combination(four, 1) + combination(twelve, 1) * combination(eight, 1) * combination(four, 1) + combination(twelve, 3);
}

vector<vector<int>> memo;
vector<vector<int>> split() {
  if(!memo.empty()) return memo;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) memo.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * X + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i + j + D[x] && 4 <= j + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i <= X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i + D[x] && 8 <= i + 2 * j + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = v[0] + v[1];
    auto b = v[0] + v[2];
    auto c = v[1] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.17391304347826086
time_ms: 50
memory_kb: 145936
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6001, vector<int>(6001));
vector<int> D(6001);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i)     ++twelve;
    else if(8 <= i) ++eight;
    else if(4 <= i) ++four;
  }
  return combination(twelve, 1)
         + combination(eight, 1) * combination(four, 1) + combination(twelve, 1) * combination(four, 1) + 2 * combination(twelve, 1) * combination(eight, 1)
         + combination(four, 3) + combination(twelve, 1) * combination(four, 2) + combination(eight, 1) * combination(four, 2) + combination(twelve, 2) * combination(four, 1) + combination(eight, 2) * combination(four, 1) + combination(twelve, 1) * combination(eight, 1) * combination(four, 1) + combination(twelve, 3);
}

vector<vector<int>> memo;
vector<vector<int>> split() {
  if(!memo.empty()) return memo;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) memo.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * E[x][x] + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i * E[x][x] + j * E[x][y] + D[x] && 4 <= j * E[x][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i * E[x][y] + D[x] && 8 <= i * E[x][y] + 2 * j * E[y][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = E[x][y] * v[0] + E[x][z] + v[1];
    auto b = E[x][y] * v[0] + E[y][z] + v[2];
    auto c = E[x][z] * v[1] + E[y][z] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 6000; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.043478260869565216
time_ms: 50
memory_kb: 145792
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6000, vector<int>(6000));
vector<int> D(6000);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  assert(false);
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i)     ++twelve;
    else if(8 <= i) ++eight;
    else if(4 <= i) ++four;
  }
  return combination(twelve, 1)
         + combination(eight, 1) * combination(four, 1) + combination(twelve, 1) * combination(four, 1) + 2 * combination(twelve, 1) * combination(eight, 1)
         + combination(four, 3) + combination(twelve, 1) * combination(four, 2) + combination(eight, 1) * combination(four, 2) + combination(twelve, 2) * combination(four, 1) + combination(eight, 2) * combination(four, 1) + combination(twelve, 1) * combination(eight, 1) * combination(four, 1) + combination(twelve, 3);
}

vector<vector<int>> memo;
vector<vector<int>> split() {
  if(!memo.empty()) return memo;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) memo.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * E[x][x] + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i * E[x][x] + j * E[x][y] + D[x] && 4 <= j * E[x][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i * E[x][y] + D[x] && 8 <= i * E[x][y] + 2 * j * E[y][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = E[x][y] * v[0] + E[x][z] + v[1];
    auto b = E[x][y] * v[0] + E[y][z] + v[2];
    auto c = E[x][z] * v[1] + E[y][z] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 3; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.043478260869565216
time_ms: 40
memory_kb: 143904
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;

int N, M, X, Y;
vector<int> A, B;
vector<vector<int>> E(6000, vector<int>(6000));
vector<int> D(6000);

LL combination(auto n, auto r) {
  if(n < r) return 0;
  LL res = 1;
  for(auto i = 0; i < r; ++i) res *= n - i;
  for(auto i = 0; i < r; ++i) res /= i + 1;
  return res;
}

LL straight() {
  auto four = 0, eight = 0, twelve = 0;
  for(auto i: D) {
    if(12 <= i)     ++twelve;
    else if(8 <= i) ++eight;
    else if(4 <= i) ++four;
  }
  return combination(twelve, 1)
         + combination(eight, 1) * combination(four, 1) + combination(twelve, 1) * combination(four, 1) + 2 * combination(twelve, 1) * combination(eight, 1)
         + combination(four, 3) + combination(twelve, 1) * combination(four, 2) + combination(eight, 1) * combination(four, 2) + combination(twelve, 2) * combination(four, 1) + combination(eight, 2) * combination(four, 1) + combination(twelve, 1) * combination(eight, 1) * combination(four, 1) + combination(twelve, 3);
}

vector<vector<int>> memo;
vector<vector<int>> split() {
  if(!memo.empty()) return memo;
  vector<int> v(3);
  function<void(int, int)> dfs = [&](auto x, auto d) {
    if(d == 3) {
      if(x == 0) memo.emplace_back(v);
      return;
    }
    for(auto i = 0; i <= min(4, x); ++i) {
      v[d] = i;
      dfs(x - i, d + 1);
    }
  };
  dfs(X, 0);
  return memo;
}

LL cube(auto x) {
  if(E[x][x] < X) return 0;
  if(2 * E[x][x] + D[x] < 12) return 0;
  return 1;
}

LL cuboidA(auto x, auto y) {
  if(E[x][x] + E[x][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][x] < i) continue;
    if(E[x][y] < j) continue;
    if(8 <= 2 * i * E[x][x] + j * E[x][y] + D[x] && 4 <= j * E[x][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidB(auto x, auto y) {
  if(E[x][y] + E[y][y] < X) return 0;
  for(auto i = 0; i < X; ++i) {
    auto j = X - i;
    if(E[x][y] < i) continue;
    if(E[y][y] < j) continue;
    if(4 <= i * E[x][y] + D[x] && 8 <= i * E[x][y] + 2 * j * E[y][y] + D[y]) return 1;
  }
  return 0;
}

LL cuboidC(auto x, auto y, auto z) {
  if(E[x][y] + E[x][z] + E[y][z] < X) return 0;
  for(auto v: split()) {
    if(E[x][y] < v[0]) continue;
    if(E[x][z] < v[1]) continue;
    if(E[y][z] < v[2]) continue;
    auto a = E[x][y] * v[0] + E[x][z] + v[1];
    auto b = E[x][y] * v[0] + E[y][z] + v[2];
    auto c = E[x][z] * v[1] + E[y][z] + v[2];
    if(4 <= a + D[x] && 4 <= b + D[y] && 4 <= c + D[z]) return 1;
  }
  return 0;
}

LL solve() {
  auto res = 0;
  set<vector<int>> used;
  for(auto i = 0; i < M; ++i) for(auto j = 1; j <= 3; ++j) {
    vector<int> L = {A[i], B[i], j};
    sort(begin(L), end(L));

    if(used.count(L)) continue;
    used.emplace(L);

    if(L[0] == L[1] && L[1] == L[2]) res += cube(L[0]);
    else if(L[0] == L[1])            res += cuboidA(L[0], L[2]);
    else if(L[1] == L[2])            res += cuboidB(L[0], L[1]);
    else                             res += cuboidC(L[0], L[1], L[2]);
  }
  return res;
}

int main() {
  cin >> N >> M >> X >> Y;
  A.resize(N);
  for(auto& i: A) cin >> i;
  B.resize(M);
  for(auto& i: B) cin >> i;

  for(auto i = 0; i < N; ++i) {
    if(i < M) {
      A[i] -= B[i];
      if(A[i] > B[i]) swap(A[i], B[i]);
      ++E[A[i]][B[i]];
    } else {
      ++D[A[i]];
    }
  }

  if(X) cout << solve() << endl;
  else  cout << straight() << endl;
}
accuracy: 0.043478260869565216
time_ms: 40
memory_kb: 143868
final_rank: 17

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define dbg(...) do{cerr<<__LINE__<<": ";dbgprint(#__VA_ARGS__, __VA_ARGS__);}while(0);

using namespace std;

namespace std{template<class S,class T>struct hash<pair<S,T>>{size_t operator()(const pair<S,T>&p)const{return ((size_t)1e9+7)*hash<S>()(p.first)+hash<T>()(p.second);}};template<class T>struct hash<vector<T>>{size_t operator()(const vector<T> &v)const{size_t h=0;for(auto i : v)h=h*((size_t)1e9+7)+hash<T>()(i)+1;return h;}};}
template<class T>ostream& operator<<(ostream &os, const vector<T> &v){os<<"[ ";rep(i,v.size())os<<v[i]<<(i==v.size()-1?" ]":", ");return os;}template<class T>ostream& operator<<(ostream &os,const set<T> &v){os<<"{ "; for(const auto &i:v)os<<i<<", ";return os<<"}";}
template<class T,class U>ostream& operator<<(ostream &os,const map<T,U> &v){os<<"{";for(const auto &i:v)os<<" "<<i.first<<": "<<i.second<<",";return os<<"}";}template<class T,class U>ostream& operator<<(ostream &os,const pair<T,U> &p){return os<<"("<<p.first<<", "<<p.second<<")";}
void dbgprint(const string &fmt){cerr<<endl;}template<class H,class... T>void dbgprint(const string &fmt,const H &h,const T&... r){cerr<<fmt.substr(0,fmt.find(","))<<"= "<<h<<" ";dbgprint(fmt.substr(fmt.find(",")+1),r...);}
typedef long long ll;typedef vector<int> vi;typedef pair<int,int> pi;const int inf = (int)1e9;const double INF = 1e12, EPS = 1e-9;
/*
namespace std{
	template<int N, class Tuple>size_t get_hash(const Tuple &t){
		return 1;
	}
	template<int N, class Tuple, class H, class ...Ts> size_t get_hash(const Tuple &t){
		return hash<H>()(get<N>(t)) + ((size_t)1e9+7)*get_hash<N+1,Tuple,Ts...>(t);
	}
	template<class ...Ts>struct hash<tuple<Ts...>>{
		size_t operator()(const tuple<Ts...>&t)const{
			return get_hash<0, tuple<Ts...>, Ts...>(t);
		}
	};
}
*/
namespace std{
    namespace
    {

        // Code from boost
        // Reciprocal of the golden ratio helps spread entropy
        //     and handles duplicates.
        // See Mike Seymour in magic-numbers-in-boosthash-combine:
        //     http://stackoverflow.com/questions/4948780

        template <class T>
        inline void hash_combine(std::size_t& seed, T const& v)
        {
            seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        }

        // Recursive template code derived from Matthieu M.
        template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
        struct HashValueImpl
        {
          static void apply(size_t& seed, Tuple const& tuple)
          {
            HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
            hash_combine(seed, std::get<Index>(tuple));
          }
        };

        template <class Tuple>
        struct HashValueImpl<Tuple,0>
        {
          static void apply(size_t& seed, Tuple const& tuple)
          {
            hash_combine(seed, std::get<0>(tuple));
          }
        };
    }

    template <typename ... TT>
    struct hash<std::tuple<TT...>> 
    {
        size_t
        operator()(std::tuple<TT...> const& tt) const
        {                                              
            size_t seed = 0;                             
            HashValueImpl<std::tuple<TT...> >::apply(seed, tt);    
            return seed;                                 
        }                                              

    };
}

template<class T> inline int num(const unordered_map<T, int> &m, T k){
	auto it = m.find(k);
	if(it == m.end()) return 0;
	return it->second;
}

int main(){
	cin.tie(0); cin.sync_with_stdio(0);
	int n, m, X, Y;
	cin >> n >> m >> X >> Y;
	vi v(n + m); rep(i, n + m) cin >> v[i];
	
	ll ans = 0;
	unordered_set<int> lens;
	unordered_map<int,int> cnt;
	unordered_map<pi,int> cnt2;
	unordered_set<tuple<int,int,int>> vis;
	rep(i, n){
		if(i < m){
			int a = v[i] - v[i + n], b = v[i + n];
			lens.insert(a);
			lens.insert(b);
			++cnt2[pi(min(a, b), max(a, b))];
		}
		else{
			++cnt[v[i]];
			lens.insert(v[i]);
		}
	}
	
	if(X == 0){
		vector<pi> vs;
		for(auto i : cnt) if(i.second >= 4) vs.emplace_back(i.first, i.second);
		sort(all(vs), [](pi a, pi b){ return a.second != b.second ? a.second < b.second : a < b; });
		rep(i, vs.size()){
			if(vs[i].second >= 12) ans++;
			if(vs[i].second >= 8) ans += (int)vs.size() - i - 1;
			for(int j = i + 1; j < vs.size(); j++){
				if(vs[j].second >= 8) ans++;
				ans += (int)vs.size() - j - 1;
			}
		}
		cout << ans << endl;
		return 0;
	}
	
	for(auto i : cnt2) for(int j : lens){
		vi l = {i.first.first, i.first.second, j};
		sort(all(l));
		
		if(vis.count(tie(l[0], l[1], l[2]))) continue;
		
		if(l[0] == l[1] && l[1] == l[2]){
			int x = min(X, num(cnt2, pi(l[0], l[1])));
			int y = num(cnt, l[0]);
			if(x == X && 2 * x + y >= 12) vis.emplace(l[0], l[1], l[2]);
		}
		else if(l[0] == l[1]){
			int x0 = min(X, num(cnt2, pi(l[0], l[1])));
			int x1 = min(X, num(cnt2, pi(l[0], l[2])));
			bool ok = 0;
			rep(i, x0+1){
				if(X - i > x1) continue;
				int a = 2 * i + X - i, c = X - i;
				if(a > 8 || c > 4) continue;
				if(a + num(cnt, l[0]) >= 8 &&
					c + num(cnt, l[2]) >= 4){
					ok = 1;
					break;
				}
			}
			if(ok) vis.emplace(l[0], l[1], l[2]);
		}
		else if(l[1] == l[2]){
			int x0 = min(X, num(cnt2, pi(l[0], l[1])));
			int x1 = min(X, num(cnt2, pi(l[1], l[2])));
			bool ok = 0;
			rep(i, x0+1){
				if(X - i > x1) continue;
				int a = i, c = i + 2*(X - i);
				if(a > 4 || c > 8) continue;
				if(a + num(cnt, l[0]) >= 4 &&
					c + num(cnt, l[2]) >= 8){
					ok = 1;
					break;
				}
			}
			if(ok) vis.emplace(l[0], l[1], l[2]);
		}
		else{
			int x0 = min(X, num(cnt2, pi(l[0], l[1])));
			int x1 = min(X, num(cnt2, pi(l[1], l[2])));
			int x2 = min(X, num(cnt2, pi(l[0], l[2])));
			bool ok = 0;
			rep(i, x0+1) rep(j, x1+1){
				if(X - i - j > x2 || i + j > X) continue;
				int a = i + (X - i - j), b = i + j, c = j + (X - i - j);
				if(a > 4 || b > 4 || c > 4) continue;
				if(a + num(cnt, l[0]) >= 4 &&
					b + num(cnt, l[1]) >= 4 &&
					c + num(cnt, l[2]) >= 4){
					ok = 1;
					break;
				}
			}
			if(ok) vis.emplace(l[0], l[1], l[2]);
		}
	}
	cout << vis.size() << endl;
	return 0;
}
accuracy: 1
time_ms: 1300
memory_kb: 3584
final_rank: 5