AtCoder Beginner Contest 279 E F

链接:Tasks - TOYOTA SYSTEMS Programming Contest 2022(AtCoder Beginner Contest 279)

E:思维题

题意:有一个长度为n的数组b,一开始b[i] = i,还有一个长度为m的数组a,每个m的第i个操作交换数组b[a[i]] 和b[a[i + 1]] , 问你每次操作除了第i次的所有操作操作后,1在哪个位置。

题解:一开始先操作m次得到此时b数组,每次操作时几下操作的元素,然后在记录下元素i在那个位置,对于每个问题,如果这次操作操作了位置1则输出另一个元素的位置,否则输出元素1的位置,复杂度o(n),具体实现看代码

int a[N];
int x[N], y[N]; // 第i次操作的数是x 和 y
int b[N], pos[N]; // i 在 位置 pos
void solve()
{
    int n, m;
    cin >>n >>m;
    for(int i = 1; i <= m; ++i) cin >> a[i];
    for(int i = 1; i <= n; ++i) b[i] = i;
    for(int i = 1; i <= m; ++i)
    {
        x[i] = b[a[i]];
        y[i] = b[a[i] + 1];
        if(x[i] > y[i]) swap(x[i], y[i]);
        swap(b[a[i]], b[a[i] + 1]);
    }
    for(int i = 1; i <= n; ++i) pos[b[i]] = i;
    for(int i = 1; i <= m; ++i)
    {
        if(x[i] == 1) cout<

F:启发式合并

题意:一开始有n个盒子和无数个小球,只有第i号小球在i号盒子中,有q次操作,操作1:将盒子y中小球加入盒子x,操作2:将第n + 1号小球放入盒子x,操作3:输出编号为x的小球所在的盒子。

题解:主要操作在于操作1我们可以使用启发式合并来进行这个操作,复杂度o(nlogn)具体看代码

vector v[N]; // i号位置有的小球
int pos[N]; // 编号为i的小球在的位置
int p[N];// 编号为i的盒子在的位置
int q[N]; //位置i上放的盒子
void solve()
{
    int n, m;
    cin >>n >>m;
    for(int i = 1; i <= n; ++i) pos[i] = p[i] = q[i] = i, v[i].push_back(i);
    while(m--)
    {
        int op, x, y;
        cin >>op;
        if(op == 1)
        {
            int x, y;
            cin >>x >>y;
            if(v[p[x]].size() < v[p[y]].size())  // 启发式合并关键操作
            {
                // 交换两个盒子
                swap(p[x], p[y]); // 交换两个盒子
                swap(q[p[x]], q[p[y]]); // 对应的位置上也要交换
            }
            for(auto &i : v[p[y]]) v[p[x]].push_back(i), pos[i] = p[x]; // 将位置p[y]的小球全都给位置p[x]
            v[p[y]].clear();
        }
        else if(op == 2)
        {
            cin >>x;
            pos[++n] = p[x];
            v[p[x]].push_back(n);
        }
        else
        {
            cin >>x;
            cout<

你可能感兴趣的:(算法,c++,数据结构)