CodeForces 1141 F Same Sum Blocks(Easy) 贪心

http://codeforces.com/problemset/problem/1141/F1

This problem is given in two editions, which differ exclusively in the constraints on the number nn .

You are given an array of integers a[1],a[2],…,a[n].a[1],a[2],…,a[n]. A block is a sequence of contiguous (consecutive) elements a[l],a[l+1],…,a[r]a[l],a[l+1],…,a[r] (1≤l≤r≤n1≤l≤r≤n ). Thus, a block is defined by a pair of indices (l,r)(l,r) .

Find a set of blocks (l1,r1),(l2,r2),…,(lk,rk)(l1,r1),(l2,r2),…,(lk,rk) such that:

  • They do not intersect (i.e. they are disjoint). Formally, for each pair of blocks (li,ri)(li,ri) and (lj,rj(lj,rj ) where i≠ji≠j either ri<ljri<lj or rj<lirj<li .
  • For each block the sum of its elements is the same. Formally,

    a[l1]+a[l1+1]+⋯+a[r1]=a[l2]+a[l2+1]+⋯+a[r2]=a[l1]+a[l1+1]+⋯+a[r1]=a[l2]+a[l2+1]+⋯+a[r2]=

    ⋯=⋯=

    a[lk]+a[lk+1]+⋯+a[rk].a[lk]+a[lk+1]+⋯+a[rk].

  • The number of the blocks in the set is maximum. Formally, there does not exist a set of blocks (l′1,r′1),(l′2,r′2),…,(l′k′,r′k′)(l1′,r1′),(l2′,r2′),…,(lk′′,rk′′) satisfying the above two requirements with k′>kk′>k 。

The picture corresponds to the first example. Blue boxes illustrate blocks.

Write a program to find such a set of blocks.

Input

The first line contains integer nn (1≤n≤501≤n≤50 ) — the length of the given array. The second line contains the sequence of elements a[1],a[2],…,a[n]a[1],a[2],…,a[n] (−105≤ai≤105−105≤ai≤105 ).

Output

In the first line print the integer kk (1≤k≤n1≤k≤n ). The following kk lines should contain blocks, one per line. In each line print a pair of indices li,rili,ri (1≤li≤ri≤n1≤li≤ri≤n ) — the bounds of the ii -th block. You can print blocks in any order. If there are multiple answers, print any of them.

Examples

Input

7
4 1 2 2 1 5 3

Output

3
7 7
2 3
4 5

Input

11
-5 -4 -3 -2 -1 0 1 2 3 4 5

Output

2
3 4
1 1

Input

4
1 1 1 1

Output

4
4 4
1 1
2 2
3 3

题目大意: 给你n个数, 你可以选取连续的任意个数字组成一个块, 则这个块的值等于数字之和,问你从这n个数中最多能选出几个块使得每个块的值相等, 要求块与块之间不相交。

思路:贪心,首先处理处前缀和数组,那么在n^2时间内可以得到一段连续区间的和,同时我们可以用map建立映射:map<int,pair<int,int> >, 前一个int指的是某个块的数值,后面的pair<int,int> 如P(j,i)表示这个块是区间[i,j]的,为什么把区间右端点放到前面呢? 这就涉及到了经典贪心问题:选取最多的区间使任意两个没有交集,这个问题是按照区间右端点从小到大排序的。那么问题就简单了, 一个块可能有多个区间,我们可以用vector来储存每个块的情况。 然后进行排序贪最大的。 下面的代码用了一种更简单的方法, 建立的是从块的值到vec数组下标的映射。(因此这个代码完全可以解决Hard版本的问题 只需要改一下数组的大小即可)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;

int a[55];
vector<P> vec[100005];
map<int,int> m;//从和到下标的映射
int sum[55];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    int k=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            P p(j,i);
            int dis=sum[j]-sum[i-1];
            if(!m[dis])
                m[dis]=++k;
            int id=m[dis];
            vec[id].push_back(p);
        }
    }
    int MAX=0,idx=0;
    for(int i=1;i<=k;i++)
    {
        int cnt=0;
        int pre=0;
        sort(vec[i].begin(),vec[i].end());
        for(int j=0;j<vec[i].size();j++)
        {
            if(vec[i][j].second>pre)
            {
                ++cnt;
                pre=vec[i][j].first;
            }
            if(cnt>MAX)
            {
                MAX=cnt;
                idx=i;
            }
        }
    }
    printf("%d\n",MAX);
    int pre=0;
    for(int i=0;i<vec[idx].size();i++)
    {
        if(vec[idx][i].second>pre)
        {
            printf("%d %d\n",vec[idx][i].second,vec[idx][i].first);
            pre=vec[idx][i].first;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiji333/article/details/88787114