CodeForces - 426C Sereja and Swaps
题目链接
https://codeforces.com/problemset/problem/426/C
解题思路
先用前缀和求出每段区间的价值和;
暴力枚举区间,枚举到的区间要与剩余部分的元素进行交换;
交换规则:枚举到的区间从小到大排序,未枚举到的部分从大到小排序,用枚举到的区间中小的换未枚举到部分中大的,最多交换k次,若接下来的交换已经无法使枚举到的区间的价值和增加,也要break。
具体实现看代码
AC代码
//未用优先队列 139ms #include<bits/stdc++.h> #define ll long long using namespace std; const int N=210; const int INF=0x3f3f3f3f; bool cmp(int a,int b) { return a>b; } int n,k,sum[N],a[N],b[N],c[N],ans=-INF; int main() { cin>>n>>k; for(int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i]; } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) { int t=sum[j]-sum[i-1],nb=0,nc=0; for(int kk=i;kk<=j;kk++) b[++nb]=a[kk];//b存枚举区间的各个元素价值 for(int kk=1;kk<i;kk++) c[++nc]=a[kk];//c存未枚举部分各个元素价值 for(int kk=j+1;kk<=n;kk++) c[++nc]=a[kk]; sort(b+1,b+nb+1);//b从小到大排序 sort(c+1,c+nc+1,cmp);//c从大到小排序 for(int p=1;p<=nb && p<=nc && p<=k && c[p]>b[p];p++)//交换超过k次、交换超过总元素个数、接下来要交换的c中的比b小,都要退出循环 t+=c[p]-b[p];//增量 ans=max(ans,t); } cout<<ans<<endl; } //优先队列 140ms #include<bits/stdc++.h> #define ll long long using namespace std; const int N=210; const int INF=0x3f3f3f3f; int n,k,sum[N],a[N],ans=-INF; priority_queue<int,vector<int>,greater<int> > b; priority_queue<int> c; int main() { cin>>n>>k; for(int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i]; } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) { int sm=sum[j]-sum[i-1]; for(int t=i;t<=j;t++) b.push(a[t]); for(int t=1;t<i;t++) c.push(a[t]); for(int t=j+1;t<=n;t++) c.push(a[t]); for(int p=1;p<=k;p++) { if(b.empty() || c.empty()) break; int bb=b.top(),cc=c.top(); b.pop(),c.pop(); if(bb<cc) sm+=cc-bb; else break; } ans=max(ans,sm); while(!b.empty()) b.pop(); while(!c.empty()) c.pop(); } cout<<ans<<endl; }
总结
看到数据规模很小,但还是不会……
还用到了前缀和小技巧,直接想不到
思维 文章被收录于专栏
思维题都会了,ACM金牌就稳了! 我骗你的!