Submission #68284445
Source Code Expand
/*
WARNING!
これはChatGPT-5の性能テストのために作成したコードです.
*/
#include <bits/stdc++.h>
using namespace std;
// ノード:正規形の長さと先頭2ビット(len==1ならaのみ有効)
struct Node {
int len; // >=0
unsigned char a, b; // len>=2: 先頭2ビット, len==1: a=唯一のビット, len==0: 未使用
Node(int L=0, int A=0, int B=0): len(L), a((unsigned char)A), b((unsigned char)B) {}
};
// 3周期の配列を構成: P[0]=a, P[1]=b, P[2]=a^b^1
static inline void makeP(unsigned char a, unsigned char b, unsigned char P[3]) {
P[0] = a & 1;
P[1] = b & 1;
P[2] = (P[0] ^ P[1] ^ 1) & 1;
}
// condLeft: 左末尾2要素のXOR(=P[r-2]^P[r-1]) == Q[k]
static inline bool condLeft(const unsigned char P[3], const unsigned char Q[3], int r, int k) {
int x = P[(r+1)%3] ^ P[(r+2)%3];
return x == Q[k];
}
// condRight: P[r-1] == Q[k]^Q[k+1]
static inline bool condRight(const unsigned char P[3], const unsigned char Q[3], int r, int k) {
int x = P[(r+2)%3];
int y = Q[k] ^ Q[(k+1)%3];
return x == y;
}
// 右の容量が0のとき(=右長1)に、左だけで何回消せるかをO(1)で数える
// 固定kに対し condLeft(r,k) を r, r-1, r-2 と見て最長runを計算
static inline int additionalLeftRun(const unsigned char P[3], const unsigned char Q[3], int r, int k, int Lcap) {
int f0 = condLeft(P,Q,r,k);
if(!f0) return 0;
int f1 = condLeft(P,Q,(r+2)%3,k);
if(!f1) return min(Lcap, 1);
int f2 = condLeft(P,Q,(r+1)%3,k);
if(!f2) return min(Lcap, 2);
return Lcap; // 常に消せる
}
// 左長が1(=Lcap==0)で右だけ消す場合をO(1)で数える。a=左唯一のビット。
// kは右の現在先頭の位相。
static inline int additionalRightRun_singleLeftBit(int a, const unsigned char Q[3], int k, int Rcap) {
if(Rcap<=0) return 0;
int r0 = (a ^ Q[k] ^ Q[(k+1)%3]);
if(r0) return 0;
if(Rcap==1) return 1;
int r1 = (a ^ Q[(k+1)%3] ^ Q[(k+2)%3]);
if(r1) return 1;
if(Rcap==2) return 2;
int r2 = (a ^ Q[(k+2)%3] ^ Q[k]);
if(r2) return 2;
// 3つとも0 → 無制限に消せる(容量の範囲で)
return Rcap;
}
// 2ノードの結合(境界での消去を定数時間で計算)
static inline Node mergeNode(const Node& L, const Node& R) {
if(L.len==0) return R;
if(R.len==0) return L;
// 右の3周期
unsigned char Q[3];
if(R.len>=2) {
makeP(R.a, R.b, Q);
} else {
// len==1 のときも便宜上Qを作る(bはダミー)
Q[0] = R.a & 1;
Q[1] = 0;
Q[2] = (Q[0]^Q[1]^1)&1;
}
// 左が長さ1の特別処理:右だけを前から削る
if(L.len==1) {
int a = L.a & 1;
int n = R.len;
int Rcap = max(0, n-1);
int k = 0;
int usedR = additionalRightRun_singleLeftBit(a, Q, k, Rcap);
int n2 = n - usedR;
int k2 = (k + (usedR%3)) % 3;
int total = 1 + n2;
if(total>=2) {
// 先頭2つは [a, 右の先頭]
unsigned char b = Q[k2];
return Node(total, a, b);
} else {
// total==1 → a のみ
return Node(1, a, 0);
}
}
// ここから左len>=2
unsigned char P[3];
makeP(L.a, L.b, P);
int m = L.len, n = R.len;
int Lcap = m - 1; // 左が境界削除で消せる最大回数
int Rcap = max(0, n - 1); // 右が境界削除で消せる最大回数
int r = m % 3; // 左末尾の位相
int k = 0; // 右先頭の位相
int usedL = 0, usedR = 0;
// 右容量が0(右len==1)→ 左だけでO(1)
if(Rcap == 0) {
int t = additionalLeftRun(P, Q, r, k, Lcap);
usedL += t;
r = (r + 2*(t%3)) % 3;
int m2 = m - usedL, n2 = n;
int total = m2 + n2;
if(total >= 2) {
if(m2 >= 2) return Node(total, L.a, L.b);
if(m2 == 1) return Node(total, L.a, Q[k]); // 右は位相kのまま
// m2==0(理論上起こりにくいが一応)
return Node(total, Q[k], Q[(k+1)%3]);
} else {
// total==1
if(m2==1) return Node(1, L.a, 0);
return Node(1, Q[k], 0);
}
}
// 両側とも容量あり → まず9状態で循環検出(容量無視)
int visited[3][3]; memset(visited, -1, sizeof(visited));
int rr = r, kk = k;
vector<pair<int,int>> st; st.reserve(16);
vector<int> ops; ops.reserve(16); // 0=L, 1=R
st.emplace_back(rr,kk);
while (true) {
if (visited[rr][kk] != -1) {
// 既出 → cycle
int start = visited[rr][kk];
// pre: [0, start), cycle: [start, ops.size())
break;
}
visited[rr][kk] = (int)ops.size();
bool Lok = condLeft(P,Q,rr,kk);
bool Rok = condRight(P,Q,rr,kk);
if(!Lok && !Rok) {
// 終端(cycle長0)
break;
}
int op = Lok ? 0 : 1;
ops.push_back(op);
if(op==0) rr = (rr+2)%3;
else kk = (kk+1)%3;
st.emplace_back(rr,kk);
}
int cycle_start = visited[rr][kk]==-1 ? (int)ops.size() : visited[rr][kk];
int pre_len = cycle_start;
int cyc_len = (int)ops.size() - cycle_start;
// 容量を考慮して実際に進める
rr = r; kk = k;
// まず前周期(高々9ステップ)
int i = 0;
for (; i < pre_len; ++i) {
bool Lok = condLeft(P,Q,rr,kk);
bool Rok = condRight(P,Q,rr,kk);
if (Lok && Lcap>0) {
--Lcap; ++usedL; rr = (rr+2)%3;
} else if (Rok && Rcap>0) {
--Rcap; ++usedR; kk = (kk+1)%3;
} else {
break;
}
}
if (i < pre_len) {
// ここで停止(容量枯渇 or どちらも不可)
if (Rcap==0) {
int t = additionalLeftRun(P, Q, rr, kk, Lcap);
usedL += t; rr = (rr + 2*(t%3)) % 3;
} else if (Lcap==0) {
int t = additionalRightRun_singleLeftBit(L.a, Q, kk, Rcap);
usedR += t; kk = (kk + (t%3)) % 3;
}
} else {
// 前周期を全部消化
if (cyc_len == 0) {
// もう終端
} else {
// 循環1回分の左右回数を数える
int cL=0, cR=0;
for (int j=cycle_start;j<(int)ops.size();++j) (ops[j]==0?cL:cR)++;
if (cL==0 && cR==0) {
// ありえないが安全策
} else if (cL==0) {
// 右だけ無限に消せる(容量の範囲で)
int take = Rcap; usedR += take; Rcap = 0; kk = (kk + (take%3)) % 3;
// 右が尽きたら左だけ追加で消せる可能性
if (Lcap>0) {
int t = additionalLeftRun(P, Q, rr, kk, Lcap);
usedL += t; rr = (rr + 2*(t%3)) % 3;
}
} else if (cR==0) {
// 左だけ無限に
int take = Lcap; usedL += take; Lcap = 0; rr = (rr + 2*(take%3)) % 3;
if (Rcap>0) {
int t = additionalRightRun_singleLeftBit(L.a, Q, kk, Rcap);
usedR += t; kk = (kk + (t%3)) % 3;
}
} else {
// 両方ある → 周期をまとめて消費
int tmaxL = Lcap / cL;
int tmaxR = Rcap / cR;
int tapply = min(tmaxL, tmaxR);
if (tapply > 0) {
usedL += tapply * cL; Lcap -= tapply * cL;
usedR += tapply * cR; Rcap -= tapply * cR;
rr = (rr + 2*((tapply*cL)%3)) % 3;
kk = (kk + ((tapply*cR)%3)) % 3;
}
// 余り(<=周期長)を1手ずつ
for (int step=0; step<cyc_len; ++step) {
bool Lok = condLeft(P,Q,rr,kk);
bool Rok = condRight(P,Q,rr,kk);
if (Lok && Lcap>0) {
--Lcap; ++usedL; rr = (rr+2)%3;
} else if (Rok && Rcap>0) {
--Rcap; ++usedR; kk = (kk+1)%3;
} else {
break;
}
}
// 一方が尽きたら片側追加分
if (Rcap==0) {
int t = additionalLeftRun(P, Q, rr, kk, Lcap);
usedL += t; rr = (rr + 2*(t%3)) % 3;
} else if (Lcap==0) {
int t = additionalRightRun_singleLeftBit(L.a, Q, kk, Rcap);
usedR += t; kk = (kk + (t%3)) % 3;
}
}
}
}
int m2 = m - usedL, n2 = n - usedR;
int total = m2 + n2;
if (total >= 2) {
if (m2 >= 2) return Node(total, L.a, L.b);
if (m2 == 1) return Node(total, L.a, Q[kk]);
return Node(total, Q[kk], Q[(kk+1)%3]);
} else {
if (m2==1) return Node(1, L.a, 0);
return Node(1, Q[kk], 0);
}
}
// ---- セグ木 ----
struct SegTree {
int n;
vector<Node> seg;
SegTree(int N=0): n(1) {
while(n < N) n <<= 1;
seg.assign(2*n, Node());
}
void build(const vector<int>& A) {
int N = (int)A.size()-1; // 1-indexed
for (int i=1;i<=N;i++) seg[n+i-1] = Node(1, A[i]&1, 0);
for (int i=n+N;i<2*n;i++) seg[i] = Node(0,0,0);
for (int i=n-1;i>=1;i--) seg[i] = mergeNode(seg[i<<1], seg[i<<1|1]);
}
void point_flip(int idx) {
int p = n + idx - 1;
int v = seg[p].len ? (seg[p].a^1) : 1; // lenは1のはず
seg[p] = Node(1, v, 0);
for (p >>= 1; p >= 1; p >>= 1) {
seg[p] = mergeNode(seg[p<<1], seg[p<<1|1]);
}
}
int answer_len() const { return seg[1].len; }
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
if(!(cin>>N)) return 0;
vector<int> A(N+1);
// A の読み取り:文字列 or 整数列の両対応
{
// 次のトークンを覗く
string s; cin >> s;
bool ok = ((int)s.size()==N);
if (ok) {
for(char c: s) if(c!='0' && c!='1'){ ok=false; break; }
}
if (ok) {
for (int i=1;i<=N;i++) A[i] = (s[i-1]-'0')&1;
} else {
// s を数として扱い直す
A[1] = stoi(s) & 1;
for (int i=2;i<=N;i++) { int x; cin>>x; A[i]=x&1; }
}
}
SegTree st(N);
st.build(A);
int Q;
cin >> Q;
while(Q--){
int i; cin >> i;
A[i] ^= 1;
st.point_flip(i);
cout << st.answer_len() << '\n';
}
return 0;
}
Submission Info
| Submission Time |
|
| Task |
D - Insert XOR |
| User |
satanic0258 |
| Language |
C++ 23 (gcc 12.2) |
| Score |
0 |
| Code Size |
11073 Byte |
| Status |
WA |
| Exec Time |
537 ms |
| Memory |
8852 KiB |
Compile Error
Main.cpp: In function ‘Node mergeNode(const Node&, const Node&)’:
Main.cpp:141:17: warning: unused variable ‘start’ [-Wunused-variable]
141 | int start = visited[rr][kk];
| ^~~~~
Judge Result
| Set Name |
Sample |
All |
| Score / Max Score |
0 / 0 |
0 / 800 |
| Status |
|
|
| Set Name |
Test Cases |
| Sample |
sample_1.txt, sample_2.txt |
| All |
1_1.txt, 1_10.txt, 1_2.txt, 1_3.txt, 1_4.txt, 1_5.txt, 1_6.txt, 1_7.txt, 1_8.txt, 1_9.txt, 2_1.txt, 2_10.txt, 2_11.txt, 2_12.txt, 2_13.txt, 2_2.txt, 2_3.txt, 2_4.txt, 2_5.txt, 2_6.txt, 2_7.txt, 2_8.txt, 2_9.txt, 3_1.txt, 3_2.txt, 3_3.txt, 3_4.txt, 3_5.txt, 3_6.txt, 4_1.txt, 4_2.txt, 4_3.txt, 4_4.txt, 5_1.txt, 5_2.txt, 5_3.txt, 5_4.txt, 5_5.txt, 6_2.txt, 6_3.txt, 6_4.txt, 6_5.txt, 6_6.txt, 6_7.txt, 6_8.txt, 6_9.txt, 7_1.txt, 7_2.txt, 7_3.txt, sample_1.txt, sample_2.txt |
| Case Name |
Status |
Exec Time |
Memory |
| 1_1.txt |
AC |
317 ms |
5480 KiB |
| 1_10.txt |
AC |
337 ms |
3928 KiB |
| 1_2.txt |
AC |
308 ms |
4388 KiB |
| 1_3.txt |
AC |
120 ms |
5804 KiB |
| 1_4.txt |
AC |
178 ms |
7872 KiB |
| 1_5.txt |
AC |
126 ms |
3692 KiB |
| 1_6.txt |
AC |
346 ms |
7820 KiB |
| 1_7.txt |
AC |
174 ms |
5436 KiB |
| 1_8.txt |
AC |
13 ms |
5896 KiB |
| 1_9.txt |
AC |
373 ms |
4632 KiB |
| 2_1.txt |
AC |
32 ms |
3504 KiB |
| 2_10.txt |
WA |
52 ms |
3580 KiB |
| 2_11.txt |
AC |
254 ms |
8216 KiB |
| 2_12.txt |
AC |
80 ms |
8076 KiB |
| 2_13.txt |
AC |
297 ms |
8120 KiB |
| 2_2.txt |
WA |
35 ms |
3572 KiB |
| 2_3.txt |
WA |
41 ms |
3556 KiB |
| 2_4.txt |
WA |
83 ms |
3432 KiB |
| 2_5.txt |
WA |
49 ms |
3588 KiB |
| 2_6.txt |
WA |
80 ms |
3512 KiB |
| 2_7.txt |
WA |
19 ms |
3500 KiB |
| 2_8.txt |
WA |
94 ms |
3424 KiB |
| 2_9.txt |
WA |
51 ms |
3692 KiB |
| 3_1.txt |
AC |
9 ms |
5704 KiB |
| 3_2.txt |
AC |
15 ms |
7840 KiB |
| 3_3.txt |
AC |
4 ms |
4328 KiB |
| 3_4.txt |
AC |
411 ms |
5988 KiB |
| 3_5.txt |
AC |
354 ms |
4096 KiB |
| 3_6.txt |
AC |
407 ms |
6044 KiB |
| 4_1.txt |
AC |
429 ms |
8376 KiB |
| 4_2.txt |
AC |
423 ms |
8376 KiB |
| 4_3.txt |
AC |
435 ms |
8296 KiB |
| 4_4.txt |
AC |
426 ms |
8372 KiB |
| 5_1.txt |
WA |
379 ms |
8080 KiB |
| 5_2.txt |
WA |
402 ms |
8084 KiB |
| 5_3.txt |
WA |
380 ms |
8180 KiB |
| 5_4.txt |
WA |
414 ms |
8112 KiB |
| 5_5.txt |
WA |
391 ms |
8120 KiB |
| 6_2.txt |
AC |
509 ms |
8124 KiB |
| 6_3.txt |
AC |
508 ms |
8076 KiB |
| 6_4.txt |
AC |
537 ms |
8216 KiB |
| 6_5.txt |
AC |
515 ms |
8180 KiB |
| 6_6.txt |
WA |
382 ms |
8780 KiB |
| 6_7.txt |
WA |
382 ms |
8816 KiB |
| 6_8.txt |
WA |
390 ms |
8760 KiB |
| 6_9.txt |
WA |
382 ms |
8852 KiB |
| 7_1.txt |
WA |
477 ms |
8032 KiB |
| 7_2.txt |
WA |
495 ms |
8064 KiB |
| 7_3.txt |
WA |
492 ms |
8104 KiB |
| sample_1.txt |
AC |
1 ms |
3480 KiB |
| sample_2.txt |
AC |
1 ms |
3544 KiB |