2024.11.2 模拟赛
T1 P11242 碧树
把 \(n\) 个点往外连即可。最终答案为 \(n - \max_{i=1}^na_i + 1\)
T2 P11243 繁花
感觉我的做法麻烦了,而且随机复杂度()
显然的,从左往右看可以分层,遇到一次大于号分一次。对于每段,遍历一遍,每遇到一次小于号计算一次答案。如果不考虑等于号,这段的贡献就是当前下标与右边离自己最近的小于号的下标之差。如果有等于号,考虑有几个等于号连着就可以了,开个 lst
维护一下下标位置就可以 \(O(1)\) 查询了。将原来的贡献乘上 \(i- lst_i\) 即可。
计算答案的时候从左往右算一遍再从右往左算一遍就可以了。
但是这么写会被卡到 \(O(n^2)\),没关系,我们继续优化,再开一个 \(ne[i]\) 维护最近的小于号,如果 \(ne_j > i\) ,那就没有必要继续往回算找答案了。直接进行下一次计算。这样复杂度可以直接优化到接近线性?不知道,反正跑的飞快。
#include <bits/stdc++.h>
#define rint register int
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e7 + 5;
char s[N], t[N];
int n;
int lst[N], ne[N];
int calc(char s[])
{
for (rint i = 1, j = 0; i <= n; i++)
{
lst[i] = j;
if (s[i] != '=') j = i;
}
for (rint i = n, j = 1e6; i >= 1; i--)
{
if (s[i] == '<') j = i;
ne[i] = j;
}
int ans = 0;
for (rint i = 1, j = 1; i <= n; i++)
{
if (s[i] == '>')
{
if (ne[j] > i) continue;
for (rint k = j; k < i; k++)
if (s[k] == '<')
{
ans += (i - k) * (k - lst[k]);
j = i;
}
}
}
return ans;
}
signed main()
{
int T;
cin >> T;
while (T--)
{
cin >> n;
for (rint i = 1; i < n; i++) cin >> s[i];
s[n] = '>';
for (rint i = 1; i < n; i++)
{
if (s[n - i] == '>') t[i] = '<';
else if (s[n - i] == '<') t[i] = '>';
else t[i] = '=';
}
t[n] = '>';
cout << calc(s) + calc(t) << endl;
}
return 0;
}
T3 P11244 吻秋
不是,这 tm 什么玩意儿,正常人不应该都想的是线段树合并维护操作 1 然后平衡树查询第 k 大吗()
赛时写完暴力后开始想正解,但是除了线段树合并 + 平衡树想不到别的做法了。但是好多人 20min 切掉 T3 又让我觉得很不可思议,感觉自己又想歪了但是好像又没歪,然后写了两个小时写了一坨跑的比暴力还慢无语了放弃了。
想到排序操作肯定有多余的,因为记录一下值域范围,如果有交集再计算否则不用管。所以我们只需要维护每一个序列的最大值最小值,然后打个 tag 让每个序列排上一次序就够用了,剩下的只需要归并排序就可以了,直接调用 merge 函数。所以只有前几次操作时暴力维护的后边的操作大概率都是 \(O(1)\) 的比个最值就行
具体复杂度证明不太会
T4 P11245 残雪
没时间了赛时就构造出了特殊性质,非常好构造题使我大脑飞速旋转。
先计算 \(L=R\) 的情况,我们假设 \(n<m\) ,那么可以理解为要去找使 \(n\) 不会被吸收的合法解的对于 \(m\) 的要求。显然,如果我们 \(L\) 个 \(L\) 个去排波峰波谷是最能让他被吸收的排法。那么只需要把周期降低为 \(L-1\),它就一定吸收不了了。那么对于 \(m\) 的限制,就是必须大于周期数乘上 \(L+1\)。
考虑 \(L<R\) 的情况。我们上边找对于 \(m\) 的限制,其实就是往 \(n\) 个波峰里面插入一定量的波谷。我们仍然按照 \(L-1\) 去排,然后每次使 \(L\) 变大去改我们的构造出来的序列,发现每 \(2L\) 个为一组,第一组为 \(L - 1\) 个波峰 \(L + 1\) 个波谷,然后往后的每一组依次解体 \(R - L\) 个波峰 直到不存在连续的波峰。那么我们的构造方案就出来了。
最后,我们假设的是 \(n<m\),不失一般性的,我们计算答案时只需要对于 \(n\) 算一遍 \(m\) 是否满足要求然后对 \(m\) 算一遍 \(n\) 是否满足要求即可。
标签:2024.11,int,rint,ne,lst,小于号,模拟 From: https://www.cnblogs.com/spaceswalker/p/18523029