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;
}
标签:1141,blocks,int,Sum,lk,l2,vec,l1,Blocks 来源: https://blog.csdn.net/xiji333/article/details/88787114