题目链接
题面
题目大意
求一个数组内连续区间和相同的区间的个数最多的数量及区间的起止位置。区间不存在交集。
题目分析
由于数据较小,n只有50,因此可以遍历区间端点求和,将和相同的区间存在数组的同一行。数组每一行的第一列用来存放区间和的值与区间和为该值的数量。对每一行按区间右端点进行排序,贪心选择数量最多的区间,将可选区间最大数量覆盖为该行第一列的区间和。最后遍历记录区间的行,选取可选区间最大数量的一行,贪心输出选择的区间端点。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{int l,r;};
node record[2500][2500];
bool cmp(node a,node b){
return a.r<b.r;
}
int num[55];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
}
int cnt=0;
for(int i=1;i<=n;i++){
int sum=0;
for(int j=i;j<=n;j++){
sum+=num[j];
int flag=1;
for(int k=0;k<cnt;k++){
if(record[k][0].l==sum){
record[k][0].r++;
record[k][record[k][0].r].l=i;
record[k][record[k][0].r].r=j;
flag=0;
break;
}
}
if(flag){
record[cnt][0].l=sum;
record[cnt][0].r=1;
record[cnt][1].l=i;
record[cnt][1].r=j;
cnt++;
}
}
}
for(int i=0;i<cnt;i++){
//cout<<i<<" "<<record[i][0].l<<" "<<record[i][0].r<<endl;
sort(record[i]+1,record[i]+1+record[i][0].r,cmp);
int tmp=1,last=1;
for(int j=2;j<=record[i][0].r;j++){
if(record[i][j].l>record[i][last].r){
tmp++;
last=j;
}
}
record[i][0].l=tmp;
}
int maxn=0,ind=0;
for(int i=0;i<cnt;i++){
if(record[i][0].l>maxn){
maxn=record[i][0].l;
ind=i;
}
}
printf("%d\n",maxn);
int lain=1;
printf("%d %d\n",record[ind][1].l,record[ind][1].r);
for(int i=2;i<=record[ind][0].r;i++){
if(record[ind][i].l>record[ind][lain].r){
printf("%d %d\n",record[ind][i].l,record[ind][i].r);
lain=i;
}
}
return 0;
}