• Codeforces Round #674 (Div. 3) D. Non-zero Segments(前缀和/尺取)垃圾做法


    Kolya got an integer array a1,a2,…,an. The array can contain both positive and negative integers, but Kolya doesn't like 0 , so the array doesn't contain any zeros.

    Kolya doesn't like that the sum of some subsegments of his array can be 0 . The subsegment is some consecutive segment of elements of the array.

    You have to help Kolya and change his array in such a way that it doesn't contain any subsegments with the sum 0 . To reach this goal, you can insert any integers between any pair of adjacent elements of the array (integers can be really any: positive, negative, 00 0 , any by absolute value, even such a huge that they can't be represented in most standard programming languages).

    Your task is to find the minimum number of integers you have to insert into Kolya's array in such a way that the resulting array doesn't contain any subsegments with the sum 0 .

    Input

    The first line of the input contains one integer n (2≤n≤200000) — the number of elements in Kolya's array.

    The second line of the input contains n integers a1,a2,…,an(−109≤ai≤109,ai≠0) — the description of Kolya's array.

    Output

    Print the minimum number of integers you have to insert into Kolya's array in such a way that the resulting array doesn't contain any subsegments with the sum 0.

    Examples

    Input

    Copy

    4
    1 -5 3 2
    

    Output

    Copy

    1
    

    Input

    Copy

    5
    4 -2 3 -9 2
    

    Output

    Copy

    0
    

    Input

    Copy

    9
    -1 1 -1 1 -1 1 1 -1 -1
    

    Output

    Copy

    6
    

    Input

    Copy

    8
    16 -5 -11 -15 10 5 4 -4
    

    Output

    Copy

    3
    

    首先我们注意到如果某一子段i~j之和为0,那么由前缀和得sum[i - 1] = sum[j]。因此用map记录前缀和,这样就能直接把所有和为0的子段找出来。因为插入的数没有限制,所以可以将问题瞎JB转化为选最少的插入的位置覆盖所有的子段,类似紫书上讲的选最少的点覆盖所有的线段(贪心地尽可能取最右边),不过这个题还要稍微处理一下。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <vector>
    using namespace std;
    int n, a[200005];
    long long sum[200005] = { 0 };
    map<long long, int> mp;
    struct Segment
    {
    	int x, y;
    };
    bool cmp(Segment a, Segment b)
    {
    	if(a.y != b.y) return a.y < b.y;
    	else return a.x < b.x;
    } 
    vector<Segment> v;
    int main()
    {
    	cin >> n;
    	for(int i = 1; i <= n; i++)
    	{
    		scanf("%d", &a[i]);
    		sum[i] = sum[i - 1] + 1ll * a[i];
    	}
    	mp[0] = 0;
    	for(int i = 1; i <= n; i++)
    	{
    		map<long long, int>::iterator it;
    		it = mp.find(sum[i]);
    		if(it != mp.end())
    		{
    			v.push_back(Segment{it->second + 1, i});
    			//mp.erase(it);
    		}
    		//else 
    		mp[sum[i]] = i;
    	}
    	//LRJ 区间选点问题 
        sort(v.begin(), v.end(), cmp);
        if(!v.size())
        {
        	cout << 0;
        	return 0;
    	}
        int ans = 1;
        int p = v[0].y - 1;
        for(int i = 1; i < v.size(); i++)
        {
            if(p < v[i].x)
            {
                ans++;
                p = v[i].y - 1;
            }
        }
        if(v.size() == 1) ans = 1;
        cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    2019年11月4日随堂测试 最多输入字母统计
    写增删改查中间遇到的问题
    2019年12月9日下午自习成果
    2019年12月16日 分级考试
    2019年11月18日 JAVA期中考试 增删改查
    sql语言积累
    【转载】Java项目中常用的异常处理情况总结
    泛型
    C#数字格式化输出
    委托,Lambda的几种用法
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13756711.html
Copyright © 2020-2023  润新知