每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Educational Codeforces Round 142 (Rated for Div. 2)(C,D)

Educational Codeforces Round 142 (Rated for Div. 2)(C,D)

C

C

这道题的大意是题目大意是给你一个任意的排序,我们要把这个排序通过任意个操作变成一个有序的排序

操作是,选择任意两个数,大的那一个放在后面,小的那一个放在后面,问最少多少个操作才可以把这个排序变成有序的

在vp的过程中,感觉快知道答案了,但还是差一点,很迷糊,一团乱麻

先理一理

对于这些数,我感性的认为(对于此时n=5)

如果要选择两个数,1和5,在一起,2和4在一起进行操作

我们可以判断我们可以设一个l,一个r,l和r是从1到l-1的是符合顺序的,r-1到n是符合顺序的

什么是符合顺序的,我们在遍历的过程中,还有一个i,l要符合顺序就要让al和i是一样的,ar和n-i+1

如果不符合顺序,那么一定会需要i次操作

因为如果i和n-i+1这一对需要进行操作i个操作,因为如果进行了这一个操作,把i变到第一个了,我们要把1变到第一个位置,那么就还需要i-1个操作,总共i个操作

#include <iostream>
#include <vector>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int t,n,a[maxn],pos[maxn];
bool vis[maxn];
void solve()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
        vis[i]=false;
    }
    int ans=0;
    int l=1,r=n;
    for (int i=1;l<r&&i<=n;i++)
    {
        while (vis[a[l]])
        {
            l++;
        }
        while (vis[a[r]])
        {
            r--;
        }
        if (l>=r) break;
        if (a[l]!=i||a[r]!=n-i+1)//l,或者r至少有一个不满足,就需要操作了
        {
            ans=i;
        }
        vis[i]=vis[n-i+1]=true;//不管操作没操作,到这儿都一定是让i和n-i+1满足条件了
    }
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

D

D

这个题的ri=qpj看半天没看懂

先讲一下题目大意吧

这个是有n个长度为m的排序

对于ai(排序)和aj(排序)的乘积可以得到一个新的排序

新的排序就是

ri=qpj

每种排序的值为从1到m的过程中,1到x是连续的1 2 3 。。。 x这种下标的数值一样的长度

问对于每一个排序,可以和某一个排序的值最大是多少

后来看了一些题解

要想ri=qpi=i,

我们可以看成qx=i,pi=x

那么我们可以理解为

q 值为i的下标x

p 下标为i的值x

可以看出两个排序的乘积值越大,可以看成是,一个是原来的排序,一个将下标和值变一下,其中最大值为这两个排序的最长公共前缀和

求最长公共前缀和可以用到字典树

字典树一定要开大一点,我这道题数据是4e5,我开了1e5都不够,至少要开到1e6那儿去

具体操作看代码

#include <iostream>
#include <vector>
using namespace std;
const int maxn=1000007;
#define int long long 
int n,m;
int tr[maxn][11];
int tot;
int t;
void insert(vector<int> s)
{
    int rt=0;
    for (int j=0;j<m;j++)
    {
        if (!tr[rt][s[j]])
        {
            tr[rt][s[j]]=++tot;
        }
        rt=tr[rt][s[j]];
    }
    return ;
}
int search(vector<int> s)
{
    int rt=0;
    for (int j=0;j<m;j++)
    {
        if (!tr[rt][s[j]]) return j;//如果这一个数没有找到,直接输出这一个的位置,因为下标是0到m-1的
        rt=tr[rt][s[j]];
    }
    return m;
}
vector<int>a[maxn],rev;
void solve()
{
    cin>>n>>m;
    rev=vector<int>(m);
    for (int i=0;i<n;i++)
    {
        a[i].clear();
        for (int j=0;j<m;j++)
        {
            int x;
            cin>>x;
            x--;//下标是从0到m-1
            a[i].push_back(x);
            rev[x]=j;
        }
        insert(rev);//rev为翻转
    }
    for (int i=0;i<n;i++)
    {
        cout<<search(a[i])<<' ';
    }
    cout<<'\n';
    for (int i=0;i<=tot;i++)//注意下一次可能会用到,要清除字典树
    {
        for (int j=0;j<10;j++)
        {
            tr[i][j]=0;
        }
    }
    tot=0;
    return ;
}
signed main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}
posted @   righting  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示