CF 1141 F Same Sum Blocks
https://codeforces.com/contest/1141/problem/F2
题意:
给一串数字,然后从中挑选出一些连续的小段,使每个片段的和相等,每小段至少一个数字.
小段之间不能相交.
找到片段数目最多的方法.
思路:
数据量不大, n<1500, n^2也不会T.
贪心, 先n*n将所有片段的和求出来, 用和当key, 保存在一个map里, 记录左右节点的序号, 每个key下都有很多种片段, 这些片段可以放在一个vector里面.
在这个vectot里面全是和相同的pair(i,j), 去找最大不相交的片段数目.(贪心)
PS:
贪心找最大不相交片段数目的时候, 一定要思考清楚怎么找得到的片段数目才是最多的.
// 1141F 同解 #include <bits/stdc++.h> using namespace std; bool cmp(pair<int,int> a, pair<int,int> b) { return a.first > b.first; } bool cmp_2(pair<int,int> a, pair<int,int> b) { return a.first < b.first; } map<int, vector<pair<int,int>>> mp; map<int, vector<pair<int,int>>> ans; int p[2000]; int sum[2000]; int main() { //freopen("test_data.txt","r",stdin); // INPUT int n; cin>>n; for(int i=0; i<n; i++) { cin>>p[i]; sum[i+1] = sum[i]+p[i]; } // DEAL int su =0; for(int i=1; i<=n; i++) { for(int j=i; j<=n; j++) { su = sum[j]-sum[i-1]; mp[su].push_back(make_pair(i,j)); } } //cout<<"map prepared!"<<endl; int max_cnt = 0; int index = 0; for(auto &itor : mp) { //cout<<"index : "<<itor.first<<endl; int cnt = 0; int pre = 500001; sort(itor.second.begin(), itor.second.end(), cmp); for(auto &it: itor.second) { //if (itor.first == -5) //cout<<"add new :"<<it.first<<"," <<it.second<<endl; if(it.second<pre) { cnt++; pre = it.first; ans[itor.first].push_back(it); } if(cnt > max_cnt) { //cout<<"cnt = "<<cnt<<endl; max_cnt = cnt; index = itor.first; } } } //cout<<"prepare to out put!"<<endl; // OUTPUT //cout<<"index = "<<index<<endl; sort(ans[index].begin(), ans[index].end(), cmp_2); cout<<ans[index].size()<<endl; for(auto &itor: ans[index]) cout<<itor.first<<" "<<itor.second<<endl; return 0; }

浙公网安备 33010602011771号