結果
| 問題 | No.3652 Range Bracket Sequence |
| コンテスト | |
| ユーザー |
とある理系大学生の日常
|
| 提出日時 | 2026-08-05 12:29:36 |
| 言語 | C++23(gcc16) (gcc 16.1.0 + boost 1.90.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 3,419 bytes |
| 記録 | |
| コンパイル時間 | 2,758 ms |
| コンパイル使用メモリ | 366,348 KB |
| 実行使用メモリ | 14,052 KB |
| 最終ジャッジ日時 | 2026-08-28 21:15:51 |
| 合計ジャッジ時間 | 6,755 ms |
|
ジャッジサーバーID (参考情報) |
judge2_0 / judge3_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 5 TLE * 1 -- * 51 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
struct Operation {
int type;
int x;
int y;
};
struct Query {
int left;
int right;
int id;
};
struct MoComparator {
int blockSize;
bool operator()(const Query& a, const Query& b) const {
int blockA = a.left / blockSize;
int blockB = b.left / blockSize;
if (blockA != blockB) {
return blockA < blockB;
}
if (blockA & 1) {
return a.right > b.right;
}
return a.right < b.right;
}
};
void solveBatch(
const string& S,
vector<Query>& queries,
vector<int>& answers
) {
if (queries.empty()) {
return;
}
const int N = static_cast<int>(S.size());
const int queryCount = static_cast<int>(queries.size());
vector<int> prefix(N + 1, 0);
for (int i = 0; i < N; ++i) {
prefix[i + 1] = prefix[i] + (S[i] == '(' ? 1 : -1);
}
const int blockSize = max(
1,
static_cast<int>(
N / max(1.0, sqrt(static_cast<double>(queryCount)))
)
);
sort(queries.begin(), queries.end(), MoComparator{blockSize});
multiset<int> values;
int currentLeft = 0;
int currentRight = -1;
for (const Query& query : queries) {
const int left = query.left;
const int right = query.right;
while (currentLeft > left) {
--currentLeft;
values.insert(prefix[currentLeft]);
}
while (currentRight < right) {
++currentRight;
values.insert(prefix[currentRight]);
}
while (currentLeft < left) {
auto it = values.find(prefix[currentLeft]);
values.erase(it);
++currentLeft;
}
while (currentRight > right) {
auto it = values.find(prefix[currentRight]);
values.erase(it);
--currentRight;
}
const int length = right - left + 1;
const int intervalSum = prefix[right] - prefix[left - 1];
const int closeCount = (length - intervalSum) / 2;
const int minimumPrefix = *values.begin();
const int unmatchedClose = max(
0,
prefix[left - 1] - minimumPrefix
);
const int matchedPairs = closeCount - unmatchedClose;
answers[query.id] = matchedPairs * 2;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
cin >> N >> Q;
string S;
cin >> S;
vector<Operation> operations(Q);
int answerCount = 0;
for (int i = 0; i < Q; ++i) {
cin >> operations[i].type
>> operations[i].x
>> operations[i].y;
if (operations[i].type == 2) {
++answerCount;
}
}
vector<int> answers(answerCount);
vector<Query> batch;
int answerId = 0;
for (const Operation& operation : operations) {
if (operation.type == 2) {
batch.push_back({
operation.x,
operation.y,
answerId
});
++answerId;
} else {
solveBatch(S, batch, answers);
batch.clear();
S[operation.x - 1] =
(operation.y == 1 ? '(' : ')');
}
}
solveBatch(S, batch, answers);
for (int answer : answers) {
cout << answer << '\n';
}
return 0;
}
とある理系大学生の日常