Codeforces Round 1047 (Div. 3)(A~F|G待补)

这次比赛还是比较好想的,但是被C卡了(把C作为了最后一题做)

比赛链接:https://codeforces.com/contest/2137

A.Collatz Conjecture

思路:一直乘2,最多倍增20次,远远不到INT_MAX

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 3e5 + 5;
struct s {
    ll l,r,id;
    friend bool operator<(const s& a, const s& b) {
        if(a.l!=b.l)return a.l<b.l;
        else return a.r<b.r;
        // return a.v < b.v;
    }
};
ll e[4] = { 0,1,0,-1 };
ll d[4] = { 1,0,-1,0 }; 
void solve() {
    ll x,k;
    cin>>x>>k;
    swap(x,k);
    for(ll i=1;i<=k;i++){
        x*=2;
    }
    cout<<x<<endl;
}
int main() {
    fio();
    ll t = 1;
   cin>>t;
    while (t--)solve();
    return 0;
}

B.Fun Permutation

思路:把所有数补成对应位置之和为n+1就行了

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 3e5 + 5;
struct s {
    ll l,r,id;
    friend bool operator<(const s& a, const s& b) {
        if(a.l!=b.l)return a.l<b.l;
        else return a.r<b.r;
        // return a.v < b.v;
    }
};
ll e[4] = { 0,1,0,-1 };
ll d[4] = { 1,0,-1,0 }; 
void solve() {
    ll n;
    cin>>n;
    vector<ll>a(n+2); 
    for(ll i=1;i<=n;i++)cin>>a[i];
    for(ll i=1;i<=n;i++)cout<<n-a[i]+1<<" ";
    cout<<endl;
}
int main() {
    fio();
    ll t = 1;
   cin>>t;
    while (t--)solve();
    return 0;
}

C.Maximum Even Sum

思路:分类讨论下。

\[首先基本思想:设 b = e \cdot f, \\ 如果 a \cdot k + \frac{b}{k} 要变大,那么就说明 \frac{b}{k} < a, \\ 且这个 \frac{b}{k} 越小就越好。\\ \]

\[如果 a 为偶数,b 为偶数,那么只要 \frac{b}{k} 不为奇数, \\ 那么都是可能答案,根据基本思想,可以得出 \frac{b}{2} \cdot a + 2 \]

\[如果a为奇数,b为奇数,那么可以得出答案为a \cdot b +1 \]

\[如果a为奇数,b为偶数,那么必须从b中拿出一个偶数乘以a,所以\frac{b}{2} % 2!=0,则无解 ,否则答案为\frac{b}{2} \cdot a+2 \]

\[如果a为偶数,b为奇数,则无解 \]

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 3e5 + 5;
struct s {
    ll l,r,id;
    friend bool operator<(const s& a, const s& b) {
        if(a.l!=b.l)return a.l<b.l;
        else return a.r<b.r;
        // return a.v < b.v;
    }
};
ll e[4] = { 0,1,0,-1 };
ll d[4] = { 1,0,-1,0 }; 
void solve() {
    ll a,b;
    cin>>a>>b;
    if(((a&1)^(b&1))!=0){
        if(b%2==1)cout<<-1<<endl;
        else{ 
            if((b/2)%2==1)cout<<-1<<endl;
            else{
                cout<<a*(b/2)+2<<endl;
            }
        }
    }
    else {
        if(a%2==0){
            // if((b/2)%2==1)cout<<a+b<<endl;
            cout<<a*(b/2)+2<<endl;
        }
        else {
            cout<<a*b+1<<endl;
        }
    }
}
int main() {
    fio();
    ll t = 1;
    cin>>t;
    while (t--)solve();
    return 0;
}

D.Replace with Occurrences

思路:对于给出数组中一个值x来看,如果x出现x次,那么肯定是可以的,但是出现x的倍数也对,因为x个1和x个2,x出现了2*x次。所以只要去检验每个数的出现次数%自己是否等于0。如果都是,则根据给出数字x的位置,x个,x个赋值即可

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 3e5 + 5;
struct s {
    ll l,r,id;
    friend bool operator<(const s& a, const s& b) {
        if(a.l!=b.l)return a.l<b.l;
        else return a.r<b.r;
        // return a.v < b.v;
    }
};
ll e[4] = { 0,1,0,-1 };
ll d[4] = { 1,0,-1,0 }; 
void solve() {
    ll n;
    cin>>n;
    vector<ll>a(n+2),b(n+2,0);
    for(ll i=1;i<=n;i++){
        cin>>a[i];
        b[a[i]]++;
    }
    ll cc=0;
    set<ll>u;
    vector<vector<ll>>pos(n+2);
    for(ll i=1;i<=n;i++){
        if(b[a[i]]%a[i]!=0)cc++;
        pos[a[i]].push_back(i);
        u.insert(a[i]);
    }
    if(cc>0)cout<<-1<<endl;
    else {
        ll l=1;
        for(auto j:u){
            ll cnt=0;
            for(auto k:pos[j]){
                cnt++;
                a[k]=l;
                if(cnt%j==0)l++;
            }
        }
        for(ll i=1;i<=n;i++)cout<<a[i]<<" ";
        cout<<endl;
    }
}
int main() {
    fio();
    ll t = 1;
   cin>>t;
    while (t--)solve();
    return 0;
}

E.Mexification

思路:不妨设0-x在数组中只出现了一次,那么他们总是不会变化的,会变化的只会是出现了重复数,或者突然断开了如0~x,x+5.中的x+5,我们可以枚举下,发现其值变化状态很快收敛于两种。这里直接让它跑了max(k,60),最后看k-max(k,60)的奇偶性即可,如果奇性再来一次变化即可

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 3e5 + 5;
struct s {
    ll l,r,id;
    friend bool operator<(const s& a, const s& b) {
        if(a.l!=b.l)return a.l<b.l;
        else return a.r<b.r;
        // return a.v < b.v;
    }
};
ll e[4] = { 0,1,0,-1 };
ll d[4] = { 1,0,-1,0 }; 
void solve() {
    ll n,k;
    cin>>n>>k;
    vector<ll>a(n+2),b(n+2);
    for(ll i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a.begin()+1,a.begin()+1+n);
    for(ll i=1;i<=min(k,60ll);i++){
        b=a;
        vector<ll>vis(n+5,0);
        ll l=0;
        for(ll j=1;j<=n;j++){
            vis[b[j]]++;
            if(b[j]==l)l++;
        }
        for(ll j=1;j<=n;j++){
            if(b[j]<=l){
                if(vis[b[j]]==1)continue;
                else b[j]=l;
            }
            else {
                b[j]=l;
            }
        }
        a=b;
    }
    ll ans=0;
    k-=min(k,60ll);
    if(k%2==0){
        for(ll j=1;j<=n;j++){
            ans+=b[j];
        }
    }
    else {
          vector<ll>vis(n+5,0);
        ll l=0;
        for(ll j=1;j<=n;j++){
            vis[b[j]]++;
            if(b[j]==l)l++;
        }
        for(ll j=1;j<=n;j++){
            if(b[j]<=l){
                if(vis[b[j]]==1)continue;
                else b[j]=l;
            }
            else {
                b[j]=l;
            }
        }
        for(ll j=1;j<=n;j++){
            ans+=b[j];
        }
    }
    cout<<ans<<endl;
}
int main() {
    fio();
    ll t = 1;
   cin>>t;
    while (t--)solve();
    return 0;
}

F.Prefix Maximum Invariance

思路:这里采用了线段树+贡献法

\[从左往右枚举i. 用线段树维护遍历完了的每个位置的对应值的最大位置(有点绕) 如果a[i]==b[i],那么这个位置能对的状态数为i*(n-i+1) \]

\[否则可以取线段树维护中max(a[i],b[i])-2*n的最大值,注意1e18直接跳,否则答案就是pos*(n-i+1) ,最后把所有贡献加起来即可 \]

#pragma GCC optimize(3, "Ofast", "inline", "unroll-loops")   
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll                            long long 
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           ???????
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
// const ll N = 5e5 + 10;
// const ull p=1145161651561;
ll ksm(ll x, ll y)
{
    ll ans = 1;
    while (y)
    {
        if (y & 1)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        y >>= 1;
    }
    return ans % mod;
}
void fio()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
const ll N = 4e5 + 5;
struct tree {
    ll v;
    ll l, r;
}p[N << 2];
void build(ll i, ll l, ll r) {
    p[i].l = l, p[i].r = r;
    p[i].v = 0;
    if (l == r)return;
    build(i << 1, l, l + r >> 1);
    build(i << 1 | 1, (l + r >> 1) + 1, r);
}
void update(ll i, ll tar, ll x) {//大
    if (p[i].l == p[i].r) {
        p[i].v = x;
        return;
    }
    ll mid = p[i].l + p[i].r >> 1;
    if (tar <= mid)update(i << 1, tar, x);
    else update(i << 1 | 1, tar, x);
    p[i].v = max(p[i << 1].v, p[i << 1 | 1].v);
}
ll query(ll i, ll l, ll r) {
    ll ans = 0;
    if (p[i].l == l && p[i].r == r) {
        return p[i].v;
    }
    ll mid = p[i].l + p[i].r >> 1;
    if (l <= mid)ans = max(ans, query(i << 1, l, min(mid, r)));
    if (r >= mid + 1)ans = max(ans, query(i << 1 | 1, max(mid + 1, l), r));
    return ans;
}
void solve() {
    ll n;
    cin >> n;
    vector<ll>a(n + 2);
    vector<ll>b(n + 2);
    build(1, 1, 2 * n);
    for (ll i = 1; i <= n; i++)cin >> a[i];
    for (ll i = 1; i <= n; i++)cin >> b[i];
    ll ans = 0;
    for (ll i = 1; i <= n; i++) {
        if (a[i] == b[i])ans += i * (n - i + 1);
        else if(i>1){
            ll cc = query(1, max(a[i], b[i]), 2 * n);
            if (cc != 0) {
                ans += cc * (n - i + 1);
            }
        }
        update(1, a[i], i);
    }
  //  if (a[1] == b[1])ans += n - 1;
    cout << ans << endl;


}
int main() {
    fio();
    ll t = 1;
    cin >> t;
    while (t--)solve();
    return 0;
}
posted @ 2025-09-08 15:10  长皆  阅读(393)  评论(2)    收藏  举报