Codeforces Round 1016 (Div. 3)(A~G)

比赛链接:https://codeforces.com/contest/2093
首次赛时龟速Akdiv3,这次头有点晕,写得很慢,很多题写得不够简约,考虑过个几天优化下吧。不要嫌弃我菜,哈哈。
E和G,Tle了.这次nlognlogn时间复杂度容易被卡,直接更新了题解。

A. Ideal Generator

思路:一上来完全没搞懂题目意思。看懂了后,就是偶数输出NO,奇数输出YES.因为偶数长度的回文数组造不出奇数

    #include<iostream>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<algorithm>
    #include<deque>
    #include<cctype>
    #include<string.h>
    #include<cstring>
    #include<math.h>
    #include<time.h>
    #include<random>
    #include<functional>
    #include<stack>
    #include<unordered_map>
    #include<string>
    #include<bitset>
    #define ll                           long long 
    // #define lowbit(x) (x & -x)
    //#define endl "\n"//                           交互题记得删除
    // #include <ext/pb_ds/assoc_container.hpp>
    // #include <ext/pb_ds/tree_policy.hpp>
    // using namespace __gnu_pbds;
    using namespace std;
    mt19937 rnd(time(0));
    const ll mod = 998244353;
    //const ll p=rnd()%mod;
    #define F first
    #define S second
    // tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
    ll ksm(ll x, ll y)//快速幂
    {
        ll ans = 1;
        x %= mod;
        while (y)
        {
            if (y & 1)
            {
                ans = ans * x % mod;
            }
            x = x * x % mod;
            y >>= 1;
        }
        return ans % mod;
    }
    ll gcd(ll x, ll y)
    {
        if (y == 0)
            return x;
        else
            return gcd(y, x % y);
    }
    ll lcm(ll x, ll y)
    {
        x /= gcd(x, y);
        return y * x;
    }
    // inline ll read()//快读
    // {
    //     register ll x = 0, f = 1;
    //     char c = getchar();
    //     while (c < '0' || c>'9')
    //     {
    //         if (c == '-') f = -1;
    //         c = getchar();
    //     }
    //     while (c >= '0' && c <= '9')
    //     {
    //         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
    //         c = getchar();
    //     }
    //     return x * f;
    // }
    struct ss
    {
        ll l,r;
        friend bool operator<(const ss& a, const ss& b)
        {
            return a.l< b.l;
        };
    };
    void fio()//加速流
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    }
    ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
    ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
    const ll N = 50005;
    int main()
    {
        fio();
        ll t;
        cin>>t;
        while(t--)
        {
            ll n;
            cin>>n;
            if(n&1)cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    //3 132 
    //6 132465
    //

B. Expensive Number

思路:最小成本肯定是删除到有且仅有一个数位且大于0得数。那么我们直接保留最后一个大于0的数位,删除前面大于0的数位(因为允许前导0,这样子做最佳)+后面0的个数。

    #include<iostream>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<algorithm>
    #include<deque>
    #include<cctype>
    #include<string.h>
    #include<cstring>
    #include<math.h>
    #include<time.h>
    #include<random>
    #include<functional>
    #include<stack>
    #include<unordered_map>
    #include<string>
    #include<bitset>
    #define ll                           long long 
    // #define lowbit(x) (x & -x)
    //#define endl "\n"//                           交互题记得删除
    // #include <ext/pb_ds/assoc_container.hpp>
    // #include <ext/pb_ds/tree_policy.hpp>
    // using namespace __gnu_pbds;
    using namespace std;
    mt19937 rnd(time(0));
    const ll mod = 998244353;
    //const ll p=rnd()%mod;
    #define F first
    #define S second
    // tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
    ll ksm(ll x, ll y)//快速幂
    {
        ll ans = 1;
        x %= mod;
        while (y)
        {
            if (y & 1)
            {
                ans = ans * x % mod;
            }
            x = x * x % mod;
            y >>= 1;
        }
        return ans % mod;
    }
    ll gcd(ll x, ll y)
    {
        if (y == 0)
            return x;
        else
            return gcd(y, x % y);
    }
    ll lcm(ll x, ll y)
    {
        x /= gcd(x, y);
        return y * x;
    }
    // inline ll read()//快读
    // {
    //     register ll x = 0, f = 1;
    //     char c = getchar();
    //     while (c < '0' || c>'9')
    //     {
    //         if (c == '-') f = -1;
    //         c = getchar();
    //     }
    //     while (c >= '0' && c <= '9')
    //     {
    //         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
    //         c = getchar();
    //     }
    //     return x * f;
    // }
    struct ss
    {
        ll l,r;
        friend bool operator<(const ss& a, const ss& b)
        {
            return a.l< b.l;
        };
    };
    void fio()//加速流
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    }
    ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
    ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
    const ll N = 50005;
    int main()
    {
      fio();
      ll t;
      cin>>t;
      while(t--)
      {
        string f;
        cin>>f;
        ll ans=0;
        ll pd=0;
        for(ll i=0;i<f.size();i++)
        {
            if(f[i]>='1')ans++,pd=i;
        }
        for(ll i=pd;i<f.size();i++)
        {
            ans+=(f[i]=='0');
        }
        ans--;
        ans=max(ans,(ll)0);
        cout<<ans<<endl;
      }
    }
    //3 132 
    //6 132465
    //

C. Simple Repetition

思路:看这道题时晕了,忘记了例如1313,其实能被13整除,卡了挺久。一开始还以为是个暴力。首先合数不管怎么样都不能变成质数。其次特判1,当k=1,其不是合数也不是质数,当k=2,其刚好为11,正好为质数,其他一定是合数。当k>=2,原本是质数的数将不能构造出质数,因为原质数就是因子之一。综上答案得出

    #include<iostream>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<algorithm>
    #include<deque>
    #include<cctype>
    #include<string.h>
    #include<cstring>
    #include<math.h>
    #include<time.h>
    #include<random>
    #include<functional>
    #include<stack>
    #include<unordered_map>
    #include<string>
    #include<bitset>
    #define ll                           long long 
    // #define lowbit(x) (x & -x)
    //#define endl "\n"//                           交互题记得删除
    // #include <ext/pb_ds/assoc_container.hpp>
    // #include <ext/pb_ds/tree_policy.hpp>
    // using namespace __gnu_pbds;
    using namespace std;
    mt19937 rnd(time(0));
    const ll mod = 998244353;
    //const ll p=rnd()%mod;
    #define F first
    #define S second
    // tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
    ll ksm(ll x, ll y)//快速幂
    {
        ll ans = 1;
        x %= mod;
        while (y)
        {
            if (y & 1)
            {
                ans = ans * x % mod;
            }
            x = x * x % mod;
            y >>= 1;
        }
        return ans % mod;
    }
    ll gcd(ll x, ll y)
    {
        if (y == 0)
            return x;
        else
            return gcd(y, x % y);
    }
    ll lcm(ll x, ll y)
    {
        x /= gcd(x, y);
        return y * x;
    }
    // inline ll read()//快读
    // {
    //     register ll x = 0, f = 1;
    //     char c = getchar();
    //     while (c < '0' || c>'9')
    //     {
    //         if (c == '-') f = -1;
    //         c = getchar();
    //     }
    //     while (c >= '0' && c <= '9')
    //     {
    //         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
    //         c = getchar();
    //     }
    //     return x * f;
    // }
    struct ss
    {
        ll l,r;
        friend bool operator<(const ss& a, const ss& b)
        {
            return a.l< b.l;
        };
    };
    void fio()//加速流
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    }
    ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
    ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
    const ll N = 50005;
    int main()
    {
      fio();
      ll t;
      cin>>t;
      while(t--)
      {
        ll n,k;
        cin>>n>>k;
        if(n==1)
        {
            if(k==1)cout<<"NO"<<endl;
            else if(k==2)cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
            continue;
        }
        ll pd=0;
        for(ll i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                pd=1;
                break;
            }
        }
        if(pd)cout<<"NO"<<endl;//如果是合数
        else if(k==1)cout<<"YES"<<endl;//质数就是质数
        else cout<<"NO"<<endl;
      }
    }
    //3 132 
    //6 132465
    //

D. Skibidi Table

思路:推荐不要看我的。有点头晕,直接暴力写了。每次递归我会去问对应的行和列的区间,然后根据题目要求在进行划分区间。写过线段树的人肯定非常熟悉区间划分,这里不细讲了。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll l, r;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.l < b.l;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
const ll N = 50005;
int main()
{
    fio();
    ll t;
    cin >> t;
    while (t--)
    {
        ll n, q;
        cin >> n >> q;
        function<ll(ll, ll, ll, ll, ll, ll, ll, ll)>dfs = [&](ll x, ll y, ll l, ll r, ll la, ll lb, ll ra, ll rb)
            {
                if (l == r)return l;
                ll m1 = (la + lb) >> 1;
                ll m2 = (rb + ra) >> 1;
                ll len = (r - l + 1) / 4;
                if (x <= m1)
                {
                    if (y <= m2)
                    {
                        return dfs(x, y, l, l + len - 1, la, m1, ra, m2);
                    }
                    else
                    {
                        return dfs(x, y, l + len * 3, r, la, m1, m2 + 1, rb);
                    }
                }
                else
                {
                    if (y <= m2)
                    {
                        return dfs(x, y, l + 2 * len, l + 3 * len - 1, m1 + 1, lb, ra, m2);
                    }
                    else
                    {
                        return dfs(x, y, l + len, l + len * 2 - 1, m1 + 1, lb, m2 + 1, rb);
                    }
                }
            };
        function<pair<ll, ll>(ll, ll, ll, ll, ll, ll, ll)>fs = [&](ll d, ll l, ll r, ll la, ll lb, ll ra, ll rb)
            {
                //pair<ll,,ll>
                if (l == r)
                {
                    pair<ll, ll>j = { la,ra };
                    return j;
                }
                ll len = (r - l + 1) / 4;
                ll m1 = (la + lb) >> 1;
                ll m2 = (rb + ra) >> 1;
                if (d <= l + len - 1)
                {
                    return fs(d, l, l + len - 1, la, m1, ra, m2);
                }
                else if (d <= l + 2 * len - 1)
                {
                    return fs(d, l + len, l + 2 * len - 1, m1 + 1, lb, m2 + 1, rb);
                }
                else if (d <= l + 3 * len - 1)
                {
                    return fs(d, l + 2 * len, l + 3 * len - 1, m1 + 1, lb, ra, m2);
                }
                else  return fs(d, l + 3 * len, l + 4 * len - 1, la, m1, m2 + 1, rb);
            };
        while (q--)
        {
            string f;
            cin >> f;
            if (f == "->")
            {
                ll x, y;
                cin >> x >> y;
                cout << dfs(x, y, 1ll, 1ll << (2 * n), 1ll, (1ll << n), 1ll, (1ll << n)) << endl;
            }
            else
            {
                ll d;
                cin >> d;
                pair<ll, ll>j = fs(d, 1ll, 1ll << (2 * n), 1ll, (1ll << n), 1ll, (1ll << n));
                cout << j.first << " " << j.second << endl;
            }
        }
    }
}
//3 132 
//6 132465
//

E. Min Max MEX

思路:一开始看成子序列,心理一想,如此简单?随后样例没过,又瞄了一眼,子数组!但是也不难就是了。显然答案是具有单调性的,那么我去二分下这个这个最小mex(x),在遍历过程中,为了图个方便直接用set进行查询了,这样写时间复杂度是n * logn* logn了。每次去二分下能不能形成当前mex值u,如果有u就++,否则就break。由于添加的数字是乱的,所以得写个while循环,最后判断下,是否u大于等于二分的mex值,如果满足设为0,且分组++,最后看分组有没有大于等于k,即可判断二分往哪个方向压了。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll l, r;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.l < b.l;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
const ll N = 50005;
int main()
{
    fio();
    ll t;
    cin >> t;
    while (t--)
    {
        ll n, k;
        cin >> n >> k;
        vector<ll>a(n + 5);
        ll cnt = 0;
        for (ll i = 1; i <= n; i++)
        {
            cin >> a[i];
            cnt += (a[i] == 0);
        }
        if (cnt < k)cout << 0 << endl;
        else
        {
            function<ll(ll)>ck = [&](ll x)
                {
                    ll cnt = 0;
                    set<ll>d;
                    ll u = 0;
                    for (ll i = 1; i <= n; i++)
                    {
                        if (d.size() == 0)
                        {
                            d.insert(a[i]);
                            while (1)
                            {
                                auto j = d.lower_bound(u);
                                if (j == d.end())break;
                                if (*j == u)u++;
                                else break;
                            }
                            if (u >= x)cnt++, d.clear(),u=0;
                        }
                        else
                        {
                            d.insert(a[i]);
                            while (1)
                            {
                                auto j = d.lower_bound(u);
                                if (j == d.end())break;
                                if (*j == u)u++;
                                else break;
                            }
                            if (u >= x)cnt++, d.clear(), u = 0;
                        }
                    }
                    if (cnt >= k)return 1;
                    else return 0;
                };
            ll l = 1, r = n;
            while (l <= r)
            {
                ll mid = (l + r) >> 1;
                if (ck(mid))l = mid + 1;
                else r = mid - 1;
            }
            cout << r << endl;
        }
    }
}
//3 132 
//6 132465
//

上面代码TLE了。
这里给出更新后的代码:

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
/*
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}*/
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll v, id;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.v < b.v;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
ll n, m;
vector<ll> mul(vector<ll>& a, vector<ll>& b)
{
    vector<ll>dp(m + 5);
    for (ll i = 0; i <= m - 1; i++)
    {
        for (ll j = 0; j <= m - 1; j++)
        {
            dp[(i + j) % m] = (dp[(i + j) % m] + (a[i] * b[j]) % mod) % mod;
        }
    }
    return dp;
}
vector<ll>ksm(vector<ll>& a, ll k)
{
    vector<ll>tmp(m + 5, 0);
    tmp[0] = 1;
    while (k > 0)
    {
        if (k & 1)
        {
            tmp = mul(tmp, a);
        }
        a = mul(a, a);
        k >>= 1;
    }
    return tmp;
}
bool vis[250000];
int main()
{
    fio();
    ll t;
    cin >> t;
    while (t--)
    {
        ll n, m;
        cin >> n >> m;
        vector<ll>a(n + 5);
        ll cnt = 0;
        ll f = 0;
        for (ll i = 1; i <= n; i++)
        {
            ll x;
            cin >> x;
            f += (x == 0);
            if (x >= 200001)continue;
            else a[++cnt] = x;
        }
        if (f < m)
        {
            cout << 0 << endl;
            continue;
        }
        else
        {
            function<ll(ll)>ck = [&](ll x)
                {
                    ll fo = 0;
                    ll u = 0;
                    vector<ll>fs;
                    for (ll i = 1; i <= cnt; i++)
                    {
                        vis[a[i]] = 1;
                        fs.push_back(a[i]);
                        while (vis[u])
                        {
                            u++;
                        }
                        if (u >= x)
                        {
                            fo++;
                            u = 0;
                            for (auto j : fs)vis[j] = 0;
                            fs.clear();
                        }
                    }
                    for (auto j : fs)vis[j] = 0;
                    if (fo >= m)return 1;
                    else return 0;
                };
            ll l = 1, r = cnt+1;
            while (l <= r)
            {
                ll mid = (l + r) >> 1;
                if (ck(mid))
                    l = mid + 1;
                else r = mid - 1;
            }
            cout << r << endl;
        }
    }
}

F. Hackers and Neural Networks

思路:感觉这道题没啥难度,可能是题意不太好理解?首先判断-1好弄,直接开个map<pair<ll,string>,ll>,然后遍历一遍目标数组看每个位置有没有对应字符串存在即可,有个位置没有对应字符串存在就可肯定构造不出来。有于每次是在空位随机复制字符串,这个答案问的是最坏情况的最小值。那么我们可以这么想,我们先找一个b数组,其要和目标数组所重合的字符串要最大。那么我们肯定花了n次才补全这个目标数组(有错误串),随后剩下的错误位置,我直接删一个,然后添加对应字符串即可(空位为1时,选定一个b数组,其添加的字符串肯定是相对应位置的字符串),那么答案就为n+(n-f)*2,f为某个b数组和目标数组的最大重合数。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll v, id;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.v < b.v;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
const ll N = 50005;
int main()
{
    fio();
    ll t;
    cin >> t;
    while (t--)
    {
        ll n, m;
        cin >> n >> m;
        vector<string>a;
        vector<ll>in(m+ 5, 0);
        for (ll i = 1; i <= n; i++)
        {
            string f;
            cin >> f;
            a.push_back(f);
        }
        ll op = 0;
        map<pair<ll, string>, ll>mp;
        for (ll i = 1; i <= m; i++)
        {
            for (ll j = 1; j <= n; j++)
            {
                string f;
                cin >> f;
                if (f == a[j - 1])in[i]++, op = max(op, in[i]);
                mp[{j - 1, f}]++;
            }
        }
        ll ok = 0;
        for (ll i = 0; i < a.size(); i++)
        {
            if (mp[{i, a[i]}] == 0)
            {
                ok = 1;
                break;
            }
        }
        if (ok)cout << -1 << endl;
        else
        {
             ll j = a.size() - op;
            if(op==a.size())cout<<op<<endl;
            else cout << a.size()+j*2<< endl;
        }
    }
}
//3 132 
//6 132465
//

G. Shorten the Array

思路:一看,不就是求区间两个数异或最大再套个区间限制呗。那么区间长度我二分不就好了,反正遍历下也才n * logn.然后怎么查区间两个数异或最大,我这里套了之前杭电多校的二进制trip树板子。其思想就是可持久化线段树(不了解得,可以去学学)。判断-1,就把每个数去询问全区间即可,n*31.还有就是二分遍历时,一定得把所有数作为询问数去问一遍。这里偷懒直接遍历了两次。

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll v, id;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.v < b.v;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
const ll N = 2e5 * 32 + 5;
ll tot = 0;
struct tree
{
    ll ch[2];
    ll sum;
}p[N];
void insert(ll &pos,ll f,ll x)//加入最大位置为30,那么实际需要(30+1+1)*2个点,因为要考虑二进制和累计,要比(最高位多一位+1)的容量
{
    p[++tot]=p[pos];//等于前面一个数的数值,后面直接按照之前的路走,没走的地方依然保留着,这样相当于做了前缀和
    pos=tot;
    p[pos].sum++;
    if(f<0)return;
    ll v=(x>>f)&1;
    insert(p[pos].ch[v],f-1,x);
}
ll query(ll l,ll r,ll x)
{
    ll ans=0;
    for(ll i=30;i>=0;i--)
    {
        ll k=((x>>i)&1)^1;//想要的二进制
        if(p[p[r].ch[k]].sum-p[p[l].ch[k]].sum>0)//问有没有这个位置
        {
            ans|=(1ll<<i);
            r=p[r].ch[k];//这里赋值无所谓,因为做了前缀,前面的先没(数值为0),要么同时没(数值均为0)
            l=p[l].ch[k];
        }
        else 
        {
            k^=1;
            r=p[r].ch[k];
            l=p[l].ch[k];
        }
    }
    return ans;
}
int main()
{
    ll t;
    cin >> t;
    while (t--)
    {
        tot = 0;
        ll n, k;
        cin >> n >> k;
        vector<ll>b(n + 5);
        vector<ll>a(n + 2);
        a[0] = 0;
        for (ll i = 1; i <= n; i++)
        {
            ll x;
            cin >> x;
            b[i] = x;
            a[i] = a[i - 1];//copy下前面的状态
            insert(a[i], 30, x);
        }
        ll ok = 0;
        for (ll i = 1; i <= n; i++)
        {
            ll d = query(a[0], a[n], b[i]);
            if (d >= k)ok = 1;
        }
        if (k == 0)
        {
            cout << 1 << endl;
            continue;
        }
        if (ok == 0)
        {
            cout << -1 << endl;
            continue;
        }
        ll l = 2, r = n;
        function<ll(ll)>ck = [&](ll x)
            {
                ll ok = 0;
                for (ll i = 1; i <= n - x + 1; i++)
                {
                    ll d = query(a[i], a[i + x - 1], b[i]);
                    if (d >= k)
                    {
                        ok = 1;
                        break;
                    }
                }
                if (ok)return ok;
                for (ll i = x; i <= n; i++)
                {
                    ll d = query(a[i - x], a[i], b[i]);
                    if (d >= k)
                    {
                        ok = 1;
                        break;
                    }
                }
                return ok;
            };
        while (l < r)
        {
            ll mid = (l + r) >> 1;
            if (ck(mid))
                r = mid;
            else l = mid + 1;
        }
        cout << r << endl;
    }
}

上面代码也TLE了。这里给出nlogn时间复杂度算法:

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll                           long long 
// #define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
    ll ans = 1;
    x %= mod;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
ll gcd(ll x, ll y)
{
    if (y == 0)
        return x;
    else
        return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
    x /= gcd(x, y);
    return y * x;
}
// inline ll read()//快读
// {
//     register ll x = 0, f = 1;
//     char c = getchar();
//     while (c < '0' || c>'9')
//     {
//         if (c == '-') f = -1;
//         c = getchar();
//     }
//     while (c >= '0' && c <= '9')
//     {
//         x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
//         c = getchar();
//     }
//     return x * f;
// }
struct ss
{
    ll v, id;
    friend bool operator<(const ss& a, const ss& b)
    {
        return a.v < b.v;
    };
};
void fio()//加速流
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
const ll N = 2e5 * 32 + 5;
ll tot = 0;
struct tree
{
    ll ch[2];
    ll sum;
}p[N];
void insert(ll& pos, ll f, ll x)//注意存的是双下标啊
{
    p[++tot] = p[pos];//复制一遍前面的
    pos = tot;
    p[pos].sum++;
    if (f < 0)return;
    ll v = (x >> f) & 1;
    insert(p[tot].ch[v], f - 1, x);
}
ll query(ll l, ll r, ll x)
{
    ll ans = 0;
    for (ll i = 30; i >= 0; i--)
    {
        ll f = ((x >> i) & 1) ^ 1;
        if (p[p[r].ch[f]].sum - p[p[l].ch[f]].sum > 0)
        {
            ans |= (1ll << i);
            r = p[r].ch[f];
            l = p[l].ch[f];
        }
        else
        {
            f ^= 1;
            r = p[r].ch[f];
            l = p[l].ch[f];
        }
    }
    return ans;
}
int main()
{
    ll t;
    cin >> t;
    while (t--)
    {
        tot = 0;
        ll n, k;
        cin >> n >> k;
        vector<ll>b(n + 5);
        vector<ll>a(n + 2);
        a[0] = 0;
        for (ll i = 1; i <= n; i++)
        {
            ll x;
            cin >> x;
            b[i] = x;
            a[i] = a[i - 1];//copy下前面的状态
            insert(a[i], 30, x);
        }
        ll ok = 0;
        for (ll i = 1; i <= n; i++)
        {
            ll d = query(a[0], a[n], b[i]);
            if (d >= k)ok = 1;
        }
        if (k == 0)
        {
            cout << 1 << endl;
            continue;
        }
        if (ok == 0)
        {
            cout << -1 << endl;
            continue;
        }
        ll j=1;
        ll len=1e18;
        for(ll i=1;i<=n;i++)
        {
            while(j+len-1<i)j++;
            while(query(a[j-1],a[i],b[i])>=k)
            {
                len=min(len,i-j+1);
                j++;
            }
        }
        cout<<len<<endl;
    }
}


posted @ 2025-04-09 02:01  长皆  阅读(248)  评论(0)    收藏  举报