Codeforces Round 918 (Div. 4) E. Romantic Glasses (数学 + **前缀和思想**)

尤利娅有 n n n 个杯子排成一行。其中第 i i i 个杯子装了 a i a_i ai 单位的果汁。尤利娅只用奇数杯喝水,而她的约会对象只用偶数杯喝水。

为了给她的约会对象留下好印象,尤利娅想找到一个连续的子数列,使得如果只考虑这个子数列中的杯子,尤利娅和她的约会对象喝到的果汁总量相同。请帮助她完成这个任务。

更正式地说,如果 l l l r r r 具有相同的奇偶性,那么是否存在两个索引 l , r l , r lr ,使得 1 ≤ l ≤ r ≤ n , a l + a l + 2 + a l + 4 + ⋯ + a r = a l + 1 + a l + 3 + ⋯ + a r − 1 1≤l≤r≤n , a_l+a_{l+2}+a_{l+4}+⋯+a_r=a_{l+1}+a_{l+3}+⋯+a_{r−1} 1lrnal+al+2+al+4++ar=al+1+al+3++ar1 a l + a l + 2 + a l + 4 + ⋯ + a r − 1 = a l + 1 + a l + 3 + ⋯ + a r a_l+a_{l+2}+a_{l+4}+⋯+a_{r−1}=a_{l+1}+a_{l+3}+⋯+a_r al+al+2+al+4++ar1=al+1+al+3++ar 具有相同的奇偶性。

输入
第一行包含一个整数 t ( 1 ≤ t ≤ 104 ) t ( 1≤t≤104 ) t(1t104) - 测试用例数。

每个测试用例的第一行包含一个整数 n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n ( 1≤n≤2⋅10^5 ) n(1n2105) - 眼镜总数。

每个测试用例的第二行包含 n n n 个整数 a 1 , … , a n ( 1 ≤ a i ≤ 1 0 9 ) a1,…,an ( 1≤a_i≤10^9 ) a1,,an(1ai109) --每个杯子中的果汁量。

所有测试用例中 n n n 的总和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出
对于每个测试用例,如果存在满足条件的子数组,则输出 “YES”,否则输出 “NO”。

您可以在任何情况下输出答案(例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被识别为肯定答案)。


首先根据题目的要求,我们需要找到一部分子序列使得 a l + a l + 2 + a l + 4 + ⋯ + a r = a l + 1 + a l + 3 + ⋯ + a r − 1 a_l+a_{l+2}+a_{l+4}+⋯+a_r = a_{l+1}+a_{l+3}+⋯+a_{r−1} al+al+2+al+4++ar=al+1+al+3++ar1 ,所以我们需要满足 a l + a l + 2 + a l + 4 + ⋯ + a r − [ a l + 1 + a l + 3 + ⋯ + a r − 1 ] = 0 a_l+a_{l+2}+a_{l+4}+⋯+a_r - [a_{l+1}+a_{l+3}+⋯+a_{r−1}] = 0 al+al+2+al+4++ar[al+1+al+3++ar1]=0
a l − a l + 1 + a l + 2 − a l + 3 + a l + 4 + ⋯ − − a r − 1 + a r = 0 a_l - a_{l+1} +a_{l+2} - a_{l+3} +a_{l+4}+⋯-- a_{r-1} + a_r = 0 alal+1+al+2al+3+al+4+ar1+ar=0,所以就可以想到通过前缀和来找到这样一段子序列,使得相加的和为0。

如果想要在输入的时候创造出前缀和然后进行枚举的话必定会超时,这时候就可以通过在枚举过程中维护一个前缀和就可以了,每次标记上出现的前缀和,如果在之后的遍历中搜到了相同的元素,就说明这两段前缀和相减得到的中间子段是满足题目要求的。


CODE:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define int long long

void solve(){
    int n;cin >> n;
    vector<int>a(n+1);
    for(int i = 1;i <= n;i++)cin >> a[i];

    map<int,bool>vis;
    int sum = 0;

    vis[0] = 1;

    for(int i = 1;i <= n;i++){

        if(i % 2)sum += a[i];
        else sum -= a[i];

        if(vis[sum]){
            cout << "YES\n";
            return;
        }
        vis[sum] = 1;
    }
    cout << "NO\n";
}

signed main(){
    int T;cin >> T;
    while(T--){
        solve();
    }
    return 0;
}
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值