清北刷题冲刺 11-02 p.m
函数最值
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 using namespace std; int n; long long a[maxn],ans,sum[maxn]; char s[maxn]; long long qread(){ int i=0,j=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0')i=i*10+ch-'0',ch=getchar(); return i*j; } int main(){ freopen("maximum.in","r",stdin);freopen("maximum.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++){ a[i]=qread(); sum[i]=sum[i-1]; if(a[i]>0)sum[i]=sum[i-1]+a[i]; } scanf("%s",s+1); long long c=0; for(int i=n;i>=1;i--)//枚举从哪一位开始 if(s[i]=='1'){ ans=max(ans,c+sum[i-1]); c+=max(a[i],0LL); } ans=max(ans,c); cout<<ans; }
函数最值2
#include<iostream> #include<cstdio> #include<cstring> #define maxn 1010 using namespace std; int n,k,a[maxn],pla[10000000],cnt,b[maxn]; long long ans=1000000000000000; int count(int x){ int res=0; while(x){ if(x&1)res++; x>>=1; } return res; } bool pos[maxn]; long long Abs(long long x){ if(x>=0)return x; if(x<0)return -x; } int main(){ freopen("minimum.in","r",stdin);freopen("minimum.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&k); for(int i=0;i<(1<<n);i++) if(count(i)==k)pla[++cnt]=i; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=cnt;i++){ memset(pos,0,sizeof(pos)); int p=0; int now=pla[i]; while(now){ p++; if(now&1)pos[p]=1; now>>=1; } for(int j=1;j<=n;j++){ if(pos[j]==0||j==1)b[j]=a[j]; else b[j]=b[j-1]; } long long sum=0; for(int j=2;j<=n;j++){ sum=max(sum,Abs(b[j]-b[j-1])); } ans=min(ans,sum); } cout<<ans; }
/* 二分两个数之间的差的最大值 F[i]表示i不改变的最小修改的元素个数 f[i]=min(f[j]+(i-j-1),i-1) abs(A[j]-A[i])<二分出来的答案*(i-j) */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define maxn 2010 using namespace std; int n,k,a[maxn],f[maxn]; bool check(int x){ f[1]=0; int ans=n; for(int i=2;i<=n;i++){ f[i]=i-1; for(int j=1;j<i;j++) if(abs(a[i]-a[j])<=1LL*x*(i-j)) f[i]=min(f[i],f[j]+(i-j-1));//假设改了(j~i)的数 ans=min(ans,f[i]+n-i);//假设最后一个数改了 } return ans<=k; } int main(){ freopen("minimum10.in","r",stdin); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int l=0,r=1000000001,ans=1000000001; while(l<=r){ int mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }
序列
#include<iostream> #include<cstring> #include<cstdio> #define maxn 100010 using namespace std; int n,X,Y,sum[maxn]; bool ok[1010][1010]; char s[maxn]; int Gcd(int x,int y){ if(y==0)return x; return Gcd(y,x%y); } int main(){ freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d%d%d",&n,&X,&Y); scanf("%s",s+1); for(int i=1;i<=n;i++){ sum[i]=sum[i-1]; if(s[i]=='A')sum[i]=sum[i-1]+1; } for(int len=1;len<=n;len++){//枚举长度 for(int l=1;l+len-1<=n;l++){ int r=l+len-1; int cntA=sum[r]-sum[l-1]; int cntB=len-cntA; int g=Gcd(cntA,cntB); cntA/=g;cntB/=g; if(cntA==X&&cntB==Y)ok[l][r]=1; } } int q; scanf("%d",&q); int l,r,ans; while(q--){ scanf("%d%d",&l,&r); bool flag=0; for(int len=r-l+1;len>=0;len--){ for(int i=l;i+len-1<=r;i++){ int j=i+len-1; if(ok[i][j]){ ans=len; flag=1; break; } } if(flag)break; } printf("%d\n",ans); } }
预计得分100+30+30 实际得分100+20+25 T1写了一个小时的数位dp,然后调不出来了,发现可以贪心,就写了贪心。T2T3看了没什么思路,T2前30分可以状压,T330分貌似爆搜就能过,可能代码写的丑 今天的暴力分都得的不全,希望能把暴力写的优美一点