1. 程式人生 > 其它 >錯過的比賽——ARC215: D 題題解

錯過的比賽——ARC215: D 題題解

1.前言

十幾天沒動了,好不容易找到時間去鍛鍊一下,結果就錯過了比賽,而且自己應該能加大把 rating 的。 /ts

2.題解


這道題很像這道題,所以證明就不寫了。


狀態定義:

假設現在列舉到了 \(i\), 令 \(dp[j]\) 表示子序列以 \(a[j]\) 結尾的方案數。


狀態轉移:

1. \(\forall j \in [1,i),a[j] \neq a[i]\)

\(dp[i] = (\sum_{k = 1}^{i - 1}dp[k]) + 1\)

2. \(\exists j \in [1, i), a[j] = a[i]\)

\(p = \max j (j \in [1, i), a[j] == a[i])\)

\(dp[i] = \sum_{p}^{i - 1}{dp[k]} (\forall {q < k}, a[q] \neq a[k])\)


證明:略,參考這篇題解


實現

發現式子是一個 \(O (n ^ 2)\) 的,我們考慮用資料結構優化。

如果發現 \(\exists {j < i},a[j] == a[i]\),就將 \(res -= dp[j],dp[j] = 0\),正確性顯然,就不證明了。


參考程式碼(註釋掉的是\(O (n ^ 2)\)暴力)

#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define PII pair <int, int>
#define LL long long
#define ULL unsigned long long

template <typename T> void read (T &x) { x = 0; T f = 1;char tem = getchar ();while (tem < '0' || tem > '9') {if (tem == '-') f = -1;tem = getchar ();}while (tem >= '0' && tem <= '9') {x = (x << 1) + (x << 3) + tem - '0';tem = getchar ();}x *= f; return; }
template <typename T> void write (T x) { if (x < 0) {x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0'); }
template <typename T> void print (T x, char ch) { write (x); putchar (ch); }
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }

const int Maxn = 2 * 1e5;
const LL Mod = 998244353;

int n, a[Maxn + 5];
int idx[Maxn + 5];
LL dp[Maxn + 5];

LL BIT[Maxn + 5];
int lowbit (int x) { return x & -x; }
void Update (int Index, LL x) {
	for (int i = Index; i <= Maxn; i += lowbit (i))
		BIT[i] = (BIT[i] + x + Mod) % Mod;
}
LL Query (int Index) {
	LL res = 0;
	for (int i = Index; i >= 1; i -= lowbit (i))
		res = (res + BIT[i] + Mod) % Mod;
	return res;
}
LL Calc (int l, int r) {
	return (Query (r) - Query (l - 1) + Mod) % Mod;
}

int main () {
	read (n);
	for (int i = 1; i <= n; i++) {
		read (a[i]);
	}
	
	LL res = 0;
	for (int i = 1; i <= n; i++) {
		if (idx[a[i]] == 0) {
			/*
			dp[i] = pre[i - 1] + 1;
			*/
			dp[i] = Query (i - 1) + 1;
		}
		else {
			/*
			dp[i] = (pre[i - 1] - pre[idx[a[i]] - 1] + Mod) % Mod;
			res = (res - dp[idx[a[i]]] + Mod) % Mod;
			for (int j = idx[a[i]]; j < i; j++) {
				pre[j] -= dp[idx[a[i]]];
				pre[j] = (pre[j] + Mod) % Mod;
			}
			*/
			dp[i] = Calc (idx[a[i]], i - 1);
			res = (res - dp[idx[a[i]]] + Mod) % Mod; 
			Update (idx[a[i]], -dp[idx[a[i]]]);
		}
		/*
		idx[a[i]] = i;
		pre[i] = pre[i - 1] + dp[i];
		res += dp[i];
		res %= Mod; dp[i] %= Mod; pre[i] %= Mod;
		*/
		idx[a[i]] = i;
		Update (i, dp[i]);
		res += dp[i];
		res %= Mod;
	}
	write (res);
	return 0;
}