[CF1450D] Rating Compression(树状数组+单调栈)
原题
思路
permutation要满足两个条件:1.对于长度为n的排列,最大值为n;2.排列中每个数只出现一次。
可以用树状数组记录每个数出现的次数,再用cnt记录出现超过一次的数的个数,如果从cnt == 0 && sum(n) == n ,则满足permutation条件。
接下来就是处理k每增加一,每个数出现次数的变化,可以把每次k+1序列产生的变化想成一次合并,\(b_i = min(a_i, a_{i+1})\), 形成长度为n - 1的序列,如果\(a_i > a_{i+1}\),\(ai\)就会被\(a_{i+1}\)取代,同样,如果\(a_i < a_{i-1}\), \(a_i\)就会取代\(a_{i - 1}\),那么\(a_i\)在第m次之后会被完全取代掉, m = 前面连续>ai的个数+后面连续>=ai的个数。
单调栈预处理出每个ai会被完全取代的k值,放到优先队列,对每个k值进行一次判断即可。
p.s.双指针的做法代码简单很多,但是我没想到
p.p.s.发现permutation这个词在很多题目里都像本题中的情况一样,要满足1-n不重复的出现,不知道是这个词本身可以特指这一种排列还是啥
p.p.p.s.祭奠我一周掉了200分的cf
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson rt << 1
#define rson rt << 1 | 1
#define lowbit(x) (x & (-x))
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _per(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
const int maxn = 3e5 + 7;
const int maxm = 1e3 + 7;
int n;
int a[maxn], c[maxn], pre[maxn], tail[maxn], num[maxn];
void update(int x, int y)
{
for (; x <= n; x += lowbit(x))
c[x] += y;
}
int sum(int x)
{
int ans = 0;
for (; x; x -= lowbit(x))
ans += c[x];
return ans;
}
struct node
{
int val, tim;
bool operator<(const node &a) const
{
return a.tim < tim;
}
};
void init()
{
_rep(i, 1, n)
{
num[i] = c[i] = 0;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--)
{
cin >> n;
init();
_rep(i, 1, n) cin >> a[i];
stack<pair<int, int>> s;
_rep(i, 1, n)
{
while (!s.empty() && s.top().F > a[i])
s.pop();
if (!s.empty())
pre[i] = i - s.top().S - 1;
else
pre[i] = i - 1;
s.push({a[i], i});
}
while (!s.empty())
s.pop();
_per(i, n, 1)
{
while (!s.empty() && s.top().F >= a[i])
s.pop();
if (!s.empty())
tail[i] = s.top().S - i - 1;
else
tail[i] = n - i;
s.push({a[i], i});
}
priority_queue<node> q;
int cnt = 0;
_rep(i, 1, n)
{
q.push({a[i], pre[i] + tail[i] + 1});
update(a[i], 1);
num[a[i]]++;
if (num[a[i]] == 2)
cnt++;
}
_rep(tim, 0, n - 1)
{
while (!q.empty() && q.top().tim == tim)
{
int u = q.top().val;
q.pop();
update(u, -1);
num[u]--;
if (num[u] == 1)
cnt--;
}
if (!cnt && sum(n - tim) == n - tim)
cout << 1;
else
cout << 0;
}
cout << endl;
}
}