D - Buildings
题意:N座建筑编号1-N,问第i座建筑右边有多少座建筑j使i-j之间没有建筑高于j。
思路:利用单调栈,从右向左维护一个单调递减的栈,遍历到的i的ans就是当时栈的size。
直接上code吧
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
const int maxn = 2e5 + 10;
void solve()
{
int n;
cin >> n;
std::vector<int> a(n);
for(int i = 0; i < n; i++)
cin >> a[i];
std::vector<int> ans(n);
std::vector<int> stk;
for(int i = n - 1; i >= 0; i--)
{
ans[i] = stk.size();
while(stk.size() && stk.back() < a[i]) {
stk.pop_back();
}
stk.push_back(a[i]);
}
for(int i = 0; i < n; i++)
cout << ans[i] << " \n"[i == n - 1];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
E - K-th Largest Connected Components
题意:给你n个散点。定义两种操作, 操作1:1 u v 连接u v, 操作2: 2 v k 问点v所在的联通块编号第k大的顶点。(k <= 10);
思路:利用并查集暴力维护每个联通块前10大的顶点就行
code:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
const int maxn = 2e5 + 10;
std::vector<int> e[maxn];
int anc[maxn];
int find(int x)
{
return anc[x] == x ? x : anc[x] = find(anc[x]);
}
void solve()
{
int n, q;
cin >> n >> q;
int op, v, u;
for(int i = 1; i <= n; i++)
anc[i] = i, e[i] = {i};
for(int i = 1; i <= q; i++)
{
cin >> op >> u >> v;
if(op == 1)
{
u = find(u);
v = find(v);
if(u == v) continue;
e[u].insert(e[u].end(), e[v].begin(), e[v].end());
sort(e[u].rbegin(), e[u].rend());
if(e[u].size() > 10) e[u].resize(10);
anc[v] = u;
}
if(op == 2)
{
auto & s = e[find(u)];
if(v <= (int) s.size())
{
cout << s[v - 1] << '\n';
}
else cout << "-1\n";
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
F - Teleporting Takahashi 2
题意:给一个有向环 1 -> 2 -> 3 -> 4 -> ..... -> n - > 连m条有向边(m<= 50)问从1开始经过k个顶点有多少种方案数
思路:发现m很小,考虑从此处入手,发现如果一个点i不是特殊点(没被那m条边中的一条连接的)时只能 往i + 1走,即只有特殊点会对总的方案数产生贡献,因此我们只需要考虑特殊点的状态转移就行了。当此时在特殊点时,我们只考虑往下一个最近的特殊点和另一个与该特殊点相连的特殊点进行转移。但特殊点的编号值可以取满n(小于2e5),k <= 2e5 如果暴力开dp[n][k]必然爆空间,且产生了很大的浪费,怎么解决??? 发现经典的值域大数量小,考虑离散化。方法是开一个id数组,把m个特殊点离散化,记录编号就行,这是空间被优化成m*k的,1e7级别的.. 可以接受! 具体的细节看code
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
const int maxn = 2e5 + 10;
const int mod = 998244353;
std::vector<int> e[maxn];
int dp[110][maxn];
std::vector<int> nodes = {1};
int id[maxn];
int nxt[maxn];
void solve()
{
int n, m, k;
cin >> n >> m >> k;
int x, y;
for(int i = 1; i <= m; i++)
{
cin >> x >> y;
e[x].push_back(y);
nodes.push_back(x);
nodes.push_back(y);
}
sort(nodes.begin(), nodes.end());
nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
int S = nodes.size();
nxt[nodes[S - 1]] = 1;
for(int i = 0; i < S - 1; i++){
nxt[nodes[i]] = nodes[i + 1];
}
for(int i = 0; i < S; i++) {
id[nodes[i]] = i;
}
int ans = 0;
dp[0][0] = 1;
for(int i = 0; i < k; i++)
{
for(int j = 0; j < S; j++)
{
int x = nodes[j];
for(auto k : e[x]) {
dp[id[k]][i + 1] = (dp[j][i] + dp[id[k]][i + 1]) % mod;
}
int weight = nxt[x] - x;
if(weight <= 0) weight += n;
if(i + weight > k) ans = (ans + dp[j][i]) % mod;
else dp[id[nxt[x]]][i + weight] = (dp[id[nxt[x]]][i + weight] + dp[j][i]) % mod;
}
}
for(int i = 0; i < S; i++)
ans = (ans + dp[i][k]) % mod;
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}