【题解】Codeforces 1141F. Same Sum Blocks 贪心,枚举

给一个长为 n ( 1500 ) n(1500) 的数列 a [ i ] ( ± 1 e 5 ) a[i](±1e5) ,求最多能选出几个互不相交的子段,使它们的和相等,输出方案。


只有 n ( n + 1 ) / 2 n*(n+1)/2 个区间,处理出全部的和,然后对于每个和的所有区间,求最大不重叠区间,按右端点排序的经典贪心。

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 1506, MOD = 1000000007;

int save[M], sum[M];
int dct[M*M], dcnt;
vector<pair<int,int>> vc[M*M];
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	int n = read();
	for(int i=1; i<=n; ++i)
		save[i] = read(), sum[i] = sum[i-1] + save[i];

	for(int i=1; i<=n; ++i)
		for(int j=i; j<=n; ++j)
			dct[dcnt++] = sum[j]-sum[i-1];
	sort(dct, dct+dcnt);
	dcnt = unique(dct, dct+dcnt)-dct;

	for(int i=1; i<=n; ++i)
	for(int j=1; j<=i; ++j)
	{
		int id = lower_bound(dct, dct+dcnt, sum[i]-sum[j-1])-dct;
		vc[id].push_back({j,i});
	}

	vector<pair<int,int>> ans;
	for(int i=0; i<dcnt; ++i)
	{
		//求vc[i]中最多的不相交区间个数,怎么求呢?
		vector<pair<int,int>> tmp;
		for(int j=0; j<(int)vc[i].size(); )
		{
			tmp.push_back(vc[i][j]);
			pair<int,int> tp = {vc[i][j].second, MOD};
			while(j<(int)vc[i].size() && vc[i][j]<tp) ++j;
		}
		if(tmp.size()>ans.size())
			ans = tmp;
	}
	printf("%d\n",ans.size() );
	for(auto p:ans)
		printf("%d %d\n",p.first,p.second );


    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
发布了375 篇原创文章 · 获赞 305 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/103021199
今日推荐