Codeforces Round #829、#830

这篇博客探讨了数组平衡操作(D1.Balance)的解决方案,通过使用映射记录元素出现状态,避免超时。同时,介绍了使非零和变为零的两种情况(C1/C2.MakeNonzeroSum),重点在于如何通过组合区间消除正负1的差距,以及0的影响。文章还提到了代码实现中的一些陷阱和思考过程。
摘要由CSDN通过智能技术生成

D1. Balance (Easy version)

思路:刚开始使用set查找元素超时了。之后想到我只要判断出元素在不在几何中就好,由于数组需要离散化,所以开map记录。
mp:记录元素是否出现在集合中;
a:记录该元素对应的最小倍数,及时用while暴力更新

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e5+5;
const int inf=1e18;
const int mod=998244353;
char c;int x;
map<int,int>mp,a;
void solve()
{
    mp[0]=1;
    int q;cin>>q;
    while(q--)
    {
        cin>>c>>x;
        if(c=='+')
            mp[x]=1;
        else
        {
            int tmp=a[x];
            while(mp[tmp]) tmp+=x;
            a[x]=tmp;
            cout<<tmp<<endl;
        }
    }
}
signed main()
{
    ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;
}

//int fac[N],inv[N];
//int qpow(int a,int b){
//    int res=1;
//    while(b)
//    {
//        if(b&1) res=res*a%mod;
//        a=a*a%mod;
//        b>>=1;
//    }
//    return res;
//}
//int getinv(int x){return qpow(x,mod-2);}
//int C(int a,int b)
//{
//    return (fac[a]*inv[a-b]%mod)*inv[b]%mod;
//}

C1. Make Nonzero Sum (easy version)

这题做的时候是真的么思路,觉得情况很复杂,区间的大小不好控制,正负1的也会随着位置而改变作用。知道后来,队友的出现……把我讲懂了。当时讲到每个数作为一个区间的情况,怎么就不往下再想想……
思路:
1.通常情况下,正负1的个数相等,每个数作为一个区间,肯定可以约掉。若正负1的数量加起来是个奇数,此情况无解。
2.此外若出现连续个1,则第二个1、第四个1……可转化为-1看待,两两为一组区间,直到正1和负1的数量相等。
3.若出现连续个-1,情况与2类似。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e5+5;
const int inf=1e18;
const int mod=998244353;
int n,a[N];
bool vis[N];
vector<pair<int,int>>e;
void solve()
{
    e.clear();
    cin>>n;
    for(int i=0;i<=n+5;i++) vis[i]=0;
    int num1=0,num2=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]==1) num1++;
        else if(a[i]==-1) num2++;
    }
    if((num1+num2)%2!=0)
    {
        cout<<-1<<endl;return;
    }
    if(num1==num2)
    {
        for(int i=1;i<=n;i++) e.push_back({i,i});
    }
    else if(num1>num2)
    {
        for(int i=1;i<n&&num1>num2;i++)
        {
            if(a[i]==1&&a[i+1]==1)
            {
                e.push_back({i,i+1});num1--;num2++;
                vis[i]=vis[i+1]=1;
                i++;
            }
        }
        for(int i=1;i<=n;i++)
        if(!vis[i]) e.push_back({i,i});
    }
    else
    {
        for(int i=1;i<n&&num1<num2;i++)
        {
            if(a[i]==-1&&a[i+1]==-1)
            {
                e.push_back({i,i+1});num2--;num1++;
                vis[i]=vis[i+1]=1;
                i++;
            }
        }
        for(int i=1;i<=n;i++)
        if(!vis[i]) e.push_back({i,i});
    }
    cout<<e.size()<<endl;
    sort(e.begin(),e.end(),[&](pair<int,int> &p,pair<int,int> &q){
         return p.first<q.first;
    });
    for(auto x:e)
    {
        cout<<x.first<<" "<<x.second<<endl;
    }
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

C2. Make Nonzero Sum (hard version)

思路:
1.在C1的基础上,引入了0,可分析出,在大方向正1和负1相等时,又多出两种情况。
2.0后面跟着1,可看作为-1。0后面跟着-1,可看作1.

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e5+5;
const int inf=1e18;
const int mod=998244353;
int n,a[N];
bool vis[N];
vector<pair<int,int>>e;
void solve()
{
    e.clear();
    cin>>n;
    for(int i=0;i<=n+5;i++) vis[i]=0;
    int num1=0,num2=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]==1) num1++;
        else if(a[i]==-1) num2++;
    }
    if((num1+num2)%2!=0)
    {
        cout<<-1<<endl;return;
    }
    if(num1==num2)
    {
        for(int i=1;i<=n;i++) e.push_back({i,i});
    }
    else if(num1>num2)
    {
        for(int i=1;i<n&&num1>num2;i++)
        {
            if((a[i]==1&&a[i+1]==1)||(a[i]==0&&a[i+1]==1))
            {
                e.push_back({i,i+1});num1--;num2++;
                vis[i]=vis[i+1]=1;
                i++;
            }
        }
        for(int i=1;i<=n;i++)
        if(!vis[i]) e.push_back({i,i});
    }
    else
    {
        for(int i=1;i<n&&num1<num2;i++)
        {
            if((a[i]==-1&&a[i+1]==-1)||(a[i]==0&&a[i+1]==-1))
            {
                e.push_back({i,i+1});num2--;num1++;
                vis[i]=vis[i+1]=1;
                i++;
            }
        }
        for(int i=1;i<=n;i++)
        if(!vis[i]) e.push_back({i,i});
    }
    cout<<e.size()<<endl;
    sort(e.begin(),e.end(),[&](pair<int,int> &p,pair<int,int> &q){
         return p.first<q.first;
    });
    for(auto x:e)
    {
        cout<<x.first<<" "<<x.second<<endl;
    }
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

C1. Sheikh (Easy version)

分析:这题写代码写的很差,出现了好几个小错误,都没看出来。
1.关键点:从1开始,每多出一个数值,f的值肯定是递增的,因此最大值肯定为f[n]时。
2.存在不从1开始的起点,长度为len,其值也为f[n]。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e5+5;
const int inf=1e18;
const int mod=998244353;
int n,q,a[N],mx,ll,rr;
int sum[N],xr[N];
bool check(int x)
{
    int res=0;
    for(int i=x;i<=n;i++)
    {
        int tmp=sum[i]-sum[i-x]-(xr[i]^xr[i-x]);
        if(res<=tmp)
        {
            res=tmp;ll=i-x+1,rr=i;
        }
    }
    if(res>=mx)
    {
        return 1;
    }
    else return 0;
}
void solve()
{
    cin>>n>>q;
    for(int i=0;i<=n+5;i++) sum[i]=a[i]=xr[i]=0;
    ll=rr=mx=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
        xr[i]=xr[i-1]^a[i];
    }
    int p,q;cin>>p>>q;
    mx=sum[n]-xr[n];
//    for(int i=1;i<=n;i++)
//    {
//        cout<<sum[i]<<" "<<xor[i]<<" "<<f[i]<<endl;
//    }
    int l=1,r=n,mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid))
            r=mid-1,ans=mid;
        else
            l=mid+1;
    }
    check(ans);
    cout<<ll<<" "<<rr<<endl;
}
signed main()
{
    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

E. Wish I Knew How to Sort (概率dp 待补)……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值