結果

問題 No.404 部分門松列
コンテスト
ユーザー kwm_t
提出日時 2026-06-08 20:51:13
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 155 ms / 2,000 ms
コード長 3,028 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,450 ms
コンパイル使用メモリ 380,764 KB
実行使用メモリ 15,232 KB
最終ジャッジ日時 2026-06-08 20:51:26
合計ジャッジ時間 12,208 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_0
純コード判定待ち
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 31
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
// using mint = modint1000000007;
// const int mod = 1000000007;
// using mint = modint998244353;
// const int mod = 998244353;
// const int INF = 1e9;
// const long long LINF = 1e18;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep2(i, l, r) for (int i = (l); i < (r); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rrep2(i, l, r) for (int i = (r)-1; i >= (l); --i)
#define all(x) (x).begin(), (x).end()
#define allR(x) (x).rbegin(), (x).rend()
#define P pair<int, int>
template<typename A, typename B> inline bool chmax(A &a, const B &b) { if (a < b) { a = b; return true; } return false; }
template<typename A, typename B> inline bool chmin(A &a, const B &b) { if (a > b) { a = b; return true; } return false; }

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	// 実装はchat gpt
	int N;
	cin >> N;

	vector<long long> A(N);
	for (int i = 0; i < N; i++) cin >> A[i];

	// 座圧
	vector<long long> xs = A;
	sort(xs.begin(), xs.end());
	xs.erase(unique(xs.begin(), xs.end()), xs.end());

	int M = (int)xs.size();

	vector<int> z(N);
	for (int i = 0; i < N; i++) {
		z[i] = lower_bound(xs.begin(), xs.end(), A[i]) - xs.begin();
	}

	// 値ごとの左右出現数
	vector<long long> leftCnt(M, 0), rightCnt(M, 0);

	for (int x : z) rightCnt[x]++;

	fenwick_tree<long long> bitL(M);     // 左側個数
	fenwick_tree<long long> bitR(M);     // 右側個数
	fenwick_tree<long long> prodBIT(M);  // left[v] * right[v]

	for (int v = 0; v < M; v++) {
		bitR.add(v, rightCnt[v]);
	}

	long long totalProd = 0;

	vector<long long> valueAns(M, 0);

	long long leftSize = 0;
	long long rightSize = N;

	for (int i = 0; i < N; i++) {
		int x = z[i];

		// 現在位置を右側から除去
		bitR.add(x, -1);
		rightSize--;

		rightCnt[x]--;

		long long delta = -leftCnt[x];
		prodBIT.add(x, delta);
		totalProd += delta;

		// < a[i]
		long long Lless = bitL.sum(0, x);
		long long Rless = bitR.sum(0, x);

		// > a[i]
		long long Lleq = bitL.sum(0, x + 1);
		long long Rleq = bitR.sum(0, x + 1);

		long long Lgreater = leftSize - Lleq;
		long long Rgreater = rightSize - Rleq;

		// 両端同値の除外
		long long sameLess = prodBIT.sum(0, x);

		long long sameGreater =
			totalProd - prodBIT.sum(0, x + 1);

		long long cnt =
			Lless * Rless +
			Lgreater * Rgreater -
			sameLess -
			sameGreater;

		valueAns[x] += cnt;

		// 現在位置を左側へ追加
		long long addDelta = rightCnt[x];

		leftCnt[x]++;
		bitL.add(x, 1);

		prodBIT.add(x, addDelta);
		totalProd += addDelta;

		leftSize++;
	}

	// 値ごとの累積和
	vector<long long> pref(M + 1, 0);

	for (int i = 0; i < M; i++) {
		pref[i + 1] = pref[i] + valueAns[i];
	}

	int Q;
	cin >> Q;

	while (Q--) {
		long long L, R;
		cin >> L >> R;

		int l = lower_bound(xs.begin(), xs.end(), L) - xs.begin();
		int r = upper_bound(xs.begin(), xs.end(), R) - xs.begin();

		cout << pref[r] - pref[l] << '\n';
	}
}
0