Codeforces 988C Equal Sums 题解

博客介绍了如何利用STL的map解决Codeforces上的Equal Sums问题。通过删除两个不同序列中的特定元素,使两序列和相等。文章详细阐述了思路框架和具体步骤,并提供了代码实现。

博客观赏效果更佳

题意简述

若干的序列,长度和不超过 2 e 5 2e5 2e5。请你选择两个序列,从两个序列中恰好各删除一个数,使得两个序列的和相等。如果珂以,输出"Yes",并输出是从哪两个序列中删除了编号为多少的元素。多解输出任意一个。无解输出"No"。

思路框架

STL的map维护

具体思路

对于每个序列,对于不同的元素,每个都把(序列的和-这个元素值)加入到map中,标记为出现过。如果在标记之前就出现过,由于我们在一个序列里是去重的,所以一定是前面某个序列里的。那就是出现解了。我们把(序列的和-这个元素值)保存下来,直接退出。设其为 k k k

然后,还是在去重过的序列里,看看哪几个元素满足(序列的和-这个元素值)= k k k,输出它所在的序列编号和它在序列中的编号即珂。细节还蛮多的,注意一下。

代码

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define N 255555
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)

    #define p_b push_back
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    int k;
    vector<int> a[N];int sum[N];
    void Input()
    {
        R1(k);
        F(i,1,k)
        {
            int l;R1(l);
            int S=0;
            F(j,1,l) {int x;R1(x);S+=x;a[i].push_back(x);}
            sum[i]=S;
        } 
    }

    map<int,bool> vis; //判断是否出现过
    map<int,bool> vis2; //同一个序列中去重
    void Soviet()
    {
        int kk=-1;
        bool flag=0;
        F(i,1,k)
        {
            vis2.clear(); //和vis不一样,vis2要清空一下
            F(j,0,(int)a[i].size()-1)
            {
                int x=a[i][j];
                
                if (vis2[x]) continue; //去重
                vis2[x]=1;

                if (vis[sum[i]-x]==1)
                {
                    puts("YES");
                    kk=sum[i]-x;//记录下kk
                    flag=1;break;//flag便于多层的退出
                }
                else vis[sum[i]-x]=1;
            }
            if (flag) break;
        }
        if (!flag) {puts("NO");return;} 

        int cnt=0;
        F(i,1,k)
        {
            F(j,0,(int)a[i].size()-1)
            {
                int x=a[i][j];
                if (sum[i]-x==kk)
                {
                    printf("%d %d\n",i,j+1);
                    cnt++;//我们要输出恰好两个,但是也许不止两个,所以要判一下cnt
                    break;
                }
            }
            if (cnt==2) break;
        }
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值