模拟练1
补一下最近做的模拟题:
题意:一个含n个数的序列,能否从中只删除一个数,使得剩余序列为有序序列。(不递增或不递减序列)
题解:分别判断删除一个数后是否为不递增或不递减序列,同时还需判断删除数的前后两项是否满足序列关系。例如,判断是否为不递减序列时,若a[i]<a[i-1],对于序列1 2 5 3 4 7,若删除i项3,比较其前后两项发现不符合序列关系,则考虑删除i-1项5,再比较5的前后两项判断是否符合序列关系。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=100005; 5 int a[N],n; 6 int jud1(){//判断是否为不递减序列 7 int i,f=0; 8 a[0]=0,a[n+1]=N; 9 for(i=2;i<=n;++i){ 10 if(a[i]<a[i-1]){ 11 if(f)return 0; 12 f=1; 13 if(a[i+1]>=a[i-1]||a[i]>=a[i-2])continue; 14 else return 0; 15 } 16 } 17 return 1; 18 } 19 int jud2(){//判断是否为不递增序列 20 int i,f=0; 21 a[0]=N,a[n+1]=0; 22 for(i=2;i<=n;++i){ 23 if(a[i]>a[i-1]){ 24 if(f)return 0; 25 f=1; 26 if(a[i+1]<=a[i-1]||a[i]<=a[i-2])continue; 27 else return 0; 28 } 29 } 30 return 1; 31 } 32 int main(){ 33 int t,i; 34 scanf("%d",&t); 35 while(t--){ 36 scanf("%d",&n); 37 for(i=1;i<=n;++i)scanf("%d",&a[i]); 38 if(jud1()||jud2())puts("YES"); 39 else puts("NO"); 40 } 41 return 0; 42 }
hdu5583Kingdom of Black and White
题意:给出一串01字符串,例如:0011000
2 2 3 =>2*2+2*2+3*3
最多只能改变一个数字(0->1或1->0),使得最后平方和最大
题解:暴力枚举求最大值。枚举 第i块字符数+1与第i+1块字符数-1 和 第i块字符数-1与第i+1块字符数+1的情况,注意第i+1块只有一个字符(第i,i+1,i+2会合成一块)与第i块只有一个字符时(第i-1,i,i+1会合成一块)的情况。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=100005; 5 typedef long long ll; 6 ll s[N]; 7 char a[N]; 8 int main(){ 9 int t,i,j,c=1; 10 ll ans,ma,k; 11 scanf("%d",&t); 12 while(t--){ 13 scanf("%s",a); 14 for(s[0]=0,ans=0,i=1,j=1,k=1;a[i]!='\0';++i) 15 if(a[i]!=a[i-1]){s[j++]=k;ans+=k*k;k=1;} 16 else k++; 17 s[j++]=k;ans+=k*k; 18 s[j++]=0; 19 for(ma=ans,i=1;i<j-2;++i){ 20 if(s[i+1]==1)ma=max(ma,ans-s[i]*s[i]-1-s[i+2]*s[i+2]+(s[i]+1+s[i+2])*(s[i]+1+s[i+2])); 21 else ma=max(ma,ans-s[i]*s[i]-s[i+1]*s[i+1]+(s[i]+1)*(s[i]+1)+(s[i+1]-1)*(s[i+1]-1)); 22 if(s[i]==1)ma=max(ma,ans-s[i-1]*s[i-1]-1-s[i+1]*s[i+1]+(s[i-1]+1+s[i+1])*(s[i-1]+1+s[i+1])); 23 else ma=max(ma,ans-s[i]*s[i]-s[i+1]*s[i+1]+(s[i]-1)*(s[i]-1)+(s[i+1]+1)*(s[i+1]+1)); 24 } 25 printf("Case #%d: %lld\n",c++,ma); 26 } 27 return 0; 28 }
题意:给出n个数,从中取出2个数ti,tj(ti≠tj),使得最大。
题解:用两个数组分别维护a*和 b*tj的最大值与次大值,同时记录下标,最后判断下标从而求出最大值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long ll; 5 const ll inf=0x3f3f3f3f3f3f3f3f; 6 ll a[2],b[2]; 7 int n,ida[2],idb[2]; 8 void update(ll w,int i,ll *s,int *id){ 9 if(w>s[1]){swap(s[1],w);swap(id[1],i);} 10 if(s[1]>s[0]){swap(s[1],s[0]);swap(id[1],id[0]);} 11 } 12 ll F(){ 13 if(ida[0]==idb[0])return max(a[0]+b[1],a[1]+b[0]); 14 return a[0]+b[0]; 15 } 16 int main(){ 17 int i,x,t,A,B,k=1; 18 scanf("%d",&t); 19 while(t--){ 20 a[0]=a[1]=b[0]=b[1]=-inf; 21 scanf("%d%d%d",&n,&A,&B); 22 for(i=0;i<n;++i){ 23 scanf("%d",&x); 24 update(1LL*A*x*x,i,a,ida); 25 update((ll)B*x,i,b,idb); 26 } 27 printf("Case #%d: %lld\n",k++,F()); 28 } 29 return 0; 30 }
题意:给出n和k,用k层的完全二叉树,从根节点走到叶子节点,将走过的k个数加减组成n,输出结果
题解:由数据范围n<=想到用二叉树最左边一列k个数,二进制思想构造即可(1表示加,0表示减)。最左列和为sum=-1,设需要减去的值d=sum-n,只需将d/2(如果二进制该位为0,相对于sum表示减去两倍该位代表的值)二进制中的1变为0即可。注意若n为偶数,差d为奇数,则要先将d加一,即最后一步走右节点。
1 #include<cstdio> 2 int main(){ 3 int i,t,j,k; 4 long long n,d; 5 scanf("%d",&t); 6 for(i=1;i<=t;++i){ 7 scanf("%lld%d",&n,&k); 8 printf("Case #%d:\n",i); 9 d=(1LL<<k)-1; 10 d-=n; 11 if(n%2==0)d++; 12 d/=2; 13 for(j=0;j<k-1;++j){ 14 printf("%lld ",(1LL<<j)); 15 if((1LL<<j)&d)printf("-\n"); 16 else printf("+\n"); 17 } 18 printf("%lld +\n",n&1?1LL<<(k-1):(1LL<<(k-1))+1); 19 } 20 return 0; 21 }
Codeforces526C- Om Nom and Candies
题意:有两种数量不限的糖,每种糖都有两个属性:重 w kg,欢乐值 h 。最多只能吃 C kg,求能得到的最高欢乐值。
题解:分两种情况:
①若max(wa,wb)>,假设b糖质量更大,则枚举b糖的个数,且b糖最多只能选个。
②若①不成立,则比较两糖的性价比
假设: 即wb*ha < wa*hb,说明吃wb个a糖没有吃wa个b糖划算,所以枚举性价比低的a糖,且其最多只能选的数量小于wb个(因为超过wb个则不如换成b糖)。这样两种情况的复杂度都为O()
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 int main(){ 7 long long c,ha,hb,wa,wb,ans=0; 8 int i; 9 scanf("%I64d%I64d%I64d%I64d%I64d",&c,&ha,&hb,&wa,&wb); 10 if(wa>wb){swap(wa,wb);swap(ha,hb);} 11 if(wb>=sqrt(c)){ 12 for(i=0;i<=c/wb;++i) 13 ans=max(ans,i*hb+(c-i*wb)/wa*ha); 14 } 15 else{ 16 if(ha*1./wa > (hb*1./wb)){swap(wa,wb);swap(ha,hb);} 17 for(i=0;i<wb;++i)ans=max(ans,i*ha+(c-i*wa)/wb*hb); 18 } 19 printf("%I64d\n",ans); 20 return 0; 21 }
【如有错误,敬请指正,欢迎交流】