尺取り法について、こっちの記事のほうが良いと思います。
この記事はしゃくとり法を理解してるが書き方を忘れる人向けです。
スタイリッシュでない地道な書き方のイメージとなります。
◇
方針
尺取りの範囲の左右をl,rで管理。
ただし、lを含み、rは含まない。半開区間[l,r)
①lはforで1づつ右に移動。
②その中でrを行けるところまで右に。
③rはそのままに①へもどる。
以下、プログラムのイメージ。 「 .. 」に必要な処理を入れる。
// 初期化
...
int val = 0;
int r = 0;
// lを一つずつ右に動かす。
for (int l = 0; l < n; l++)
{
if (l > r)
{
// lを右に動かしたらrを追い越した時の処理
r = l;
...
}
while(true) {
if (r >= n) {
// rが範囲の最後まで行ってる時の処理
...
break;
}
if (rの位置でも条件を満たすか) {
// rが右にいけない時の処理
...
break;
}
// rを右に移動する処理
r++;
...
}
// lを右に動かす前に値などを戻す処理
...
}
// 答えの表示など
...
◇
実例
https://atcoder.jp/contests/arc098/tasks/arc098_b
#include <iostream>
using namespace std;
using ll = long long;
int main()
{
// 方針
// 尺取りの右と左をl,rで管理。
// l→rの範囲でlを含み、rは含まない。半開区間[l,r)
// ①lはforで一個ずつ右に
// ②その中でrを行けるところまで回す。
// ③rはそのままに①へ。
// 入力の受け取り
int n;
cin >> n;
ll a[n];
for(int i = 0; i < n; i++) {
cin >> a[i];
}
// 初期化
int val = 0;
int r = 0;
ll ans = 0;
// lを一つずつ動かす。
for (int l = 0; l < n; l++)
{
// lを右に動かしたらrを追い越した時の処理
if (l > r)
{
r = l;
val = 0;
}
while(true) {
// rが範囲の最後まで行ってる時の処理
if (r >= n) {
ans += r - l;
break;
}
// rの位置でも条件を満たすか
int n_add = val + a[r];
int n_xor = val ^ a[r];
if (n_add != n_xor) {
// rが右にいけないので終了する処理
ans += r - l;
break;
}
// rを右に移動する処理
r++;
val = n_xor;
}
// lを右に動かす前に値などを戻す処理
val = val ^ a[l];
}
// 答えの表示
cout << ans << endl;
return 0;
}