粉碎题解
szh_AK_all · · 题解
验题人题解。
分析
考虑贪心。
对于每次加进来的牌的点数,可以用一个数组记录下他的匹配情况,设
对于每个加进来的点数为
第一种作用:这张牌与另一张点数相同的牌一个在排队最左边,一个在最右边,显然这是容易做到的,那么这样就可以消掉
第二种作用:可以特意将这两张牌夹着某张编号为
然后就是,多测不清空,爆龄两行泪。
Code
#include <bits/stdc++.h>
using namespace std;
int a[500005], b[500005], p[500005], gan[500005];
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
int ans = 0;
int k = 0;
for (int i = 1; i <= n; i++) {
if (b[a[i]]) {
ans = i;
p[i] = 1;//匹配过
for (int j = i - 1; j >= 1; j--) {
if (gan[j])
break;
gan[j] = 1;
if (!p[j] && a[j] != a[i])
b[a[j]] = 1000000000;
}
b[a[i]]--;
} else
b[a[i]]++;
}
for (int i = 1; i <= n; i++)
b[a[i]] = p[i] = gan[i] = 0;
cout << ans << '\n';
}
return 0;
}
可以发现,这份代码里用了一个“前缀优化”,就是由于每次修改是要修改一个前缀,而以前被修改过的地方就无需再进行修改了,这样就可以保证每个位置最多只会被修改一次,复杂度是
其实,这个优化还有一个精到之处,由于对于每次可以匹配、发挥作用的位置