D 题意:
对于给定的字符串s
定义一次变换 :s=s+change(s)
change s 是将s 中的大写字母变为小写字母,小写字母变为大写字母。
对这个字符串进行 10^100 次变换
有Q次询问,询问第 k 位的字母是什么
对于len=2 的字符串 ,
2
第一次 2+2
4+4
8+8
对于一个位置的字符,我们考虑他是由上一轮中的那一个位置的字符转换而来。一直递归找到我在初始的字符中的位置。
所以我么可以找到 这个字符 是由我一开始字符串中的那一个字符变过过来的。(其实就是 k - 上一轮的长度)
K最大是 1e18 ,因为我的字符串的长度是2 ^(轮数),所以我当前递归找的这个 是对长度取log 的。所以每一次询问的时间复杂度 接近60次。复杂度是 Q *60
这个题 在做的时候,一直在找啥规律。呃呃,属实是被简单题薄纱了
#include <bits/stdc++.h>
using namespace std;
#define int long long
string s;
char change(char ch)
{
return ch>='a'?(ch-32):(ch+32);
}
char solve(int x,bool is_reverse)
{
if (x<=s.size())
{
if (is_reverse) return change(s[x-1]);
else return s[x-1];
}
int k=s.size();
while(k*2<x)k*=2;
return solve(x-k,!is_reverse);
}
signed main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
cin>>s;
int q;cin>>q;
while(q--)
{
int pos;cin>>pos;
cout<<solve(pos,false)<<" ";
}
return 0;
}
E 题意:
能显然的看出来 是并查集。具体怎么维护信息当时没有细想。还是写题写的太少了,也是没有怎么好好想。
现在看来也是没啥思维量的题。我每次的修改之后,我只需要查询我当前集合的左边和右边集合的颜色。决定是否合并。
对于每一个集合 我们需要记录这个集合的左边界和右边界。因为这样我们才能知道这个集合相邻的集合的信息。
根据每一个集合的l r ,我们可以求得 这个集合中元素的数量,当然我们也可以直接维护好每个集合的cnt
#include <bits/stdc++.h>
using namespace std;
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x * f;
}
void solve()
{
int n, q;
cin >> n >> q;
vector<int> fa(n + 2);
vector<int> l(n + 2);
vector<int> r(n + 2);
vector<int> cnt(n + 2); // 每一个集合的大小
vector<int> col(n + 2); // 每个集合的颜色
vector<int> ans(n + 2); // 每一个颜色的个数
auto find = [&](auto &&self, int x) -> int
{
return x == fa[x] ? x : (fa[x] = self(self, fa[x]));
};
auto fun = [&](int x, int c) -> void
{
x = find(find, x);
ans[col[x]] -= cnt[x];
ans[c] += cnt[x];
col[x] = c;
};
auto unit = [&](int x, int y)
{
// 将这两个合并
int fx = find(find, x);
int fy = find(find, y);
if (fx != fy)
{
fa[fx] = fy;
l[fy] = min(l[fx], l[fy]);
r[fy] = max(r[fx], r[fy]);
cnt[fy] += cnt[fx];
}
};
for (int i = 1; i <= n; i++)
{
fa[i] = i;
l[i] = i;
r[i] = i;
cnt[i] = 1;// 这个集合中的元素数量
ans[i] = 1;
col[i] = i;
}
while (q--)
{
int op;
cin >> op;
if (op == 1)
{
int x, c;
cin >> x >> c;
fun(x, c);
int fl = find(find, l[find(find, x)] - 1);
int fr = find(find, r[find(find, x)] + 1);
if (col[fl] == c)
unit(x, fl);
if (col[fr] == c)
unit(x, fr);
}
else
{
int c;
cin >> c;
cout << ans[c] << "\n";
}
}
}
int main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
// cin>>t;
while (t--)
{
solve();
}
return 0;
}