标签:假设 过程 连续 分析 ini codeforce iostream mil 数字
考试周,但还是打了一场,一个周不打了,手生了不少.......
A:http://codeforces.com/contest/1373/problem/A
题意:
第一个商店:1个卖a元
第二个商店:打包卖,b个卖c元。比如买b+1个,那也得买双份,2b个。
求买多少(任意),第一个商店更便宜,第二个商店更便宜。不存在就-1
解析:
看a与c
如果c<a,不管怎么买,第二个商店都是比第一个商店便宜。
c>a,买一个,第一个商店肯定更便宜。然后看买b个谁优即可。
a==c,怎么买,第二个商店都更便宜。
#include<iostream> #include<cstdio> using namespace std; typedef long long ll; int main() { int t; cin>>t; while(t--) { ll a,b,c; cin>>a>>b>>c; if(c<a) { cout<<"-1 1"<<endl;continue; } if(a<c) { cout<<"1 "; if(a*(b)<=c) cout<<"-1"<<endl; else cout<<b<<endl; } if(a==c) { cout<<"-1 "<<b<<endl; } } }
B:http://codeforces.com/contest/1373/problem/B
题意:
01串,每次的操作是:找到一个连续的01,去掉。
谁最后无法操作,谁就输了。Alice先手。
解析:
刚开始想复杂了,其实直接看0,1的数目即可。
然后取一个min,这个min就是一共能得到多少个连续01串,看下奇偶即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<stack> using namespace std; typedef long long ll; int main() { int t; int x,y,k; int i; cin>>t; while(t--) { string s; cin>>s; x=0; y=0; for(i=0;i<s.size();i++) { if(s[i]==‘0‘) x++; if(s[i]==‘1‘) y++; } if(x==y) { if(x%2==0) { cout<<"NET"<<endl; continue; } else { cout<<"DA"<<endl; continue; } } else { k=min(x,y); if(k%2==0) { cout<<"NET"<<endl; continue; } else { cout<<"DA"<<endl; continue; } } } return 0; }
C:http://codeforces.com/contest/1373/problem/C
题意:
给出示例代码:
res = 0 for init = 0 to inf cur = init ok = true for i = 1 to |s| res = res + 1 if s[i] == ‘+‘ cur = cur + 1 else cur = cur - 1 if cur < 0 ok = false break if ok break
不咋好解释。。。总之就是,cur从0到inf,每次的cur都要遍历一遍字符串,遇‘+‘则+,遇‘-‘则-,res累加每次的遍历长度。当cur<0,内循环结束,当cur>0,即遍历完整串,都没有出现cur<0的情况,就结束整个。求res。
解析:
先记录个字符串的+,-过程的前缀和q[]
当cur<0的时候,res的累加就终止:
cur=x : 字符串:..........q[i]。i时结束,需要的条件是,cur从idx=1到idx=i时一路加减,cur<0了,这个时候就结束内循环,而res加上的值是 i 。
那么cur需要满足什么呢?假设q[i]=-3,那么,cur==2的时候,cur+q[i]<0,就可以终止了。即cur==-q[i]-1的时候,res+=i。用vis[]记录这个cur,vis[cur]=i。
可能要问了,cur==1的时候,+(-3)也是<0的,为什么不算呢?q[i]=-3,那么之前肯定还有q[i]=-2,-1,所以cur<2的时候已经在前面终止了,每个-q[i]-1,唯一对应一个cur。
cur越大,终止点越往后,但是我们要记录第一个终止点。vis[]也发挥了这个作用。
最后+len,因为最后res+=n,没有出现cur<0,才结束整个程序。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=1e6+10; char s[maxn]; int vis[maxn],q[maxn]; int main() { int t; cin>>t; while(t--) { scanf("%s",s+1); int len=strlen(s+1); memset(vis,0,sizeof(vis)); memset(q,0,sizeof(q)); for(int i=1;i<=len;i++) { if(s[i]==‘+‘) q[i]=1; else q[i]=-1; } q[0]=0; for(int i=1;i<=len;i++) q[i]+=q[i-1]; for(int i=1;i<=len;i++) { if(q[i]<0&&!vis[-q[i]-1]) vis[-q[i]-1]=i; } ll sum=0; for(int i=0;i<=len;i++) if(vis[i]) sum+=vis[i]; else break; cout<<sum+len<<endl; } }
D:http://codeforces.com/contest/1373/problem/D
题意:
0~n-1的数组a[],找到一个[l,r],反转里面的数字。
使得整个的a0~an-1的偶数下标的数之和最大,求这个sum。
解析:
经过分析,只有在所选长度为偶数的时候,修改才能生效。
假设有:1,2,3,4,5
原始sum=2+4
我要修改1~4,那么变成:4,3,2,1,5。sum=3+1
修改2~5,变成:1,5,4,3,2。sum=5+3
对应原始sum 2 4
3 1
5 3
2,4调换一下,可以发现,2变成了1/3,4变成了3/5,都是与相邻值发生了交换。
所以有结论:对于每一个偶数位,它要么和i-1交换,要么和i+1交换。记录这两种替换方式的最大连续和即可。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn=2e5+10; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; ll sum=0; for(int i=0;i<n;i++) { cin>>a[i]; if(i%2==0) sum+=a[i]; } ll maxx=0,ans1=0,ans2=0; for(int i=0;i<n;i+=2) { if(i+1<n) { ans1+=a[i+1]-a[i]; maxx=max(maxx,ans1); if(ans1<0) ans1=0; } if(i>1) { ans2+=a[i-1]-a[i]; maxx=max(maxx,ans2); if(ans2<0) ans2=0; } } cout<<sum+maxx<<endl; } }
Educational Codeforces Round 90 (Rated for Div. 2)A->D
标签:假设 过程 连续 分析 ini codeforce iostream mil 数字
原文地址:https://www.cnblogs.com/liyexin/p/13195994.html