又一场中国场,果然注定被虐的场。。。
A,B:都很水,差不多模拟就好了;
C题:CF难得的题意简洁,
我们可以预处理出从左到右递增的数列个数,
举个例子:1 3 2 4 5 7
L[I] 从左开始 1 2 1 2 3 4
从右往左是递减的个数: R[I] 2 1 1 3 2 1
我们发现对于i: A[I-1]<A[I+1]-1 才有可能改变A[I]找到更多的数,
ANS=MAX(ANS,MAX(L[I-1],R[I+1])+1);
具体有很多被HACK的细节,耐心处理下
代码:
#include<iostream> #include<string> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<set> #include<map> #define N 111111 using namespace std; int a[N],l[N],r[N]; int main() { int n; cin>>n; for (int i=1;i<=n;i++){ cin>>a[i]; l[i]=r[i]=1; } int ans=1; for (int i=2;i<=n;i++) { if (a[i]>a[i-1]) l[i]+=l[i-1]; ans=max(ans,l[i]); } for (int i=n-1;i>=1;i--) if (a[i]<a[i+1]) r[i]+=r[i+1]; l[0]=-1; r[n+1]=-1; a[0]=1111111111; a[n+1]=-1; for(int i=1;i<=n;i++) { if (a[i-1]<a[i+1]-1) ans=max(ans,l[i-1]+r[i+1]+1); else ans=max(ans,max(r[i+1],l[i-1])+1); } cout<<ans<<endl; return 0; }
补充D题:
我们预先统计每行,每列的和,
假如,我们选出了X行(K-X)列,那么ANS还需要减去X*(K-X)*P,好好体会这个方程式。。
然后构造优先堆,每次去最大,求出行拿1-K次,列拿1-K次,
其实代码可以看到思路
CODE:
#include<stdio.h> #include<queue> #include<math.h> #include<string.h> using namespace std; typedef long long ll; priority_queue<ll> Q; ll r[1234],c[1234],f[1234567],g[1234567]; int n,m,k,p; int main() { scanf("%d%d%d%d",&n,&m,&k,&p); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { int z; scanf("%d",&z); r[j]+=z; c[i]+=z; } while (!Q.empty()) Q.pop(); for (int i=1;i<=n;i++) Q.push(c[i]); for (int i=1;i<=k;i++) { int t=Q.top(); Q.pop(); f[i]=f[i-1]+t; Q.push(t-m*p); } while (!Q.empty()) Q.pop(); for (int i=1;i<=m;i++) Q.push(r[i]); for (int i=1;i<=k;i++) { int t=Q.top(); Q.pop(); g[i]=g[i-1]+t; Q.push(t-n*p); } ll ans=-123456789101112334ll; for (int i=0;i<=k;i++) ans=max(ans,f[i]+g[k-i]-(ll) p*(ll)i*(ll)(k-i)); printf("%I64d ",ans); return 0; }