目录
F. K-th Largest Connected Components
D. Buildings
如果正着做,对于第 x 个房子会因为前 x - 1个房子当中有高于它的而被挡住,随着 i 往后,高于它的会在界外,那就需要实时判断从 i 到 x - 1 有没有高于它的,显然不可行。
出现这个问题的原因在于第 x 个房子会受前面房子的影响。但是如果倒过来做,从后往前遍历,显然第 x 个房子不会受到它后面房子的影响,无论后面的房子比它高还是低。
正解是倒序维护一个单调队列
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, INF = 1e18;
int T, n, cnt, a[N], q[N], ans[N];
signed main()
{
cin >> n;
for (int i = 1; i <= n; i ++)
cin >> a[i];
int h = 1, t = 0;
for (int i = n; i >= 1; i --)
{
ans[i] = t - h + 1;
while (h <= t && a[q[t]] < a[i])
t --;
q[++ t] = i;
}
for (int i = 1; i <= n; i ++)
cout << ans[i] << ' ';
return 0;
}
F. K-th Largest Connected Components
维护每个集合前 10 大。每个集合要开到 20,拼接后 sort。 维护集合信息都是以每个集合的根节点作为下标。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, INF = 1e18;
int T, n, q, cnt, ans, fa[N], num[N][20];
string s;
bool cmp(int a, int b)
{
return a > b;
}
int find(int x)
{
if (x == fa[x])
return x;
return fa[x] = find(fa[x]);
}
void join(int a, int b)
{
a = find(a), b = find(b);
if (a != b)
{
fa[a] = b;
for (int i = 1; i <= 10; i ++)
num[b][i + 10] = num[a][i];
sort(num[b] + 1, num[b] + 21, cmp);
}
}
signed main()
{
cin >> n >> q;
for (int i = 1; i <= n; i ++)
{
fa[i] = i;
num[i][1] = i;
}
while (q --)
{
int opt, u, v, k;
cin >> opt;
if (opt == 1)
{
cin >> u >> v;
join(u, v);
}
if (opt == 2)
{
cin >> v >> k;
v = find(v);
if (num[v][k] == 0)
cout << "-1" << '\n';
else
cout << num[v][k] << '\n';
}
}
return 0;
}