比赛地址:https://codeforces.com/contest/1845
这次很幸运的做出来了四个题,感觉这次D题还挺简单的吧。
这次赛题难度不大,基本上就是贪心,贪心,再贪心!
A:大意就是从1-k之间,凑出来一个和为n的数,无限供应,x不能用。
解法:当x不是1的时候,直接润1。否则,如果n为奇数可以用23凑,n为偶数可以用2凑。根据这个判断一下k的范围即可。
code:
void solve() { int n,k,x; cin>>n>>k>>x; if(x!=1){ cyes; cout<<n<<endl; for(int i=1;i<=n;i++) cout<<1<<' '; cout<<endl; return; } if(n==1&&x==1){ cno; return; } if(n&1){ if(k>=3){ cyes; cout<<n/2<<endl; for(int i=1;i<=(n-3)/2;i++) cout<<2<<' '; cout<<3<<endl; }else cno; return; }else{ if(k>=2){ cyes; cout<<n/2<<endl; for(int i=1;i<=n/2;i++) cout<<2<<' '; cout<<endl; }else cno; return; } cno; }
B:大意就是给出A,B,C的坐标,求B-A,C-A的最短路中,重合的区域最大是多少。
解法:分类讨论。判断BC坐标都在A的左上左下右上右下,其他为1.
code:
void solve() { ll ax,ay,bx,by,cx,cy; cin>>ax>>ay>>bx>>by>>cx>>cy; if(bx>=ax&&cx<=ax||bx<=ax&&cx>=ax){ if(by<=ay&&cy<=ay||by>=ay&&cy>=ay){ cout<<min(abs(by-ay),abs(cy-ay))+1<<endl; }else{ cout<<1<<endl; } }else{ if(by>=ay&&cy>=ay||by<=ay&&cy<=ay){ cout<<min(abs(by-ay),abs(cy-ay))+min(abs(bx-ax),abs(cx-ax))+1<<endl; }else{ cout<<min(abs(bx-ax),abs(cx-ax))+1<<endl; } } }
C:大意就是给出一个字符串s仅0-9,给出一个长度为m的两个字符串代表上下边界。求是否能够构造一个字符串不是s的子序列,且在两个字符串范围内。
解法:直接贪心。从左到右的每一位,我们都取到一个在字符串s中的最右的一个位置,找不到时为yes。
code:
void solve() { string s,l,r; int m; cin>>s>>m>>l>>r; char mint = '9'+1,maxt = '0'-1; for(int i=s.size()-1;i>=0;i--){ mint = min(s[i],mint),maxt = max(s[i],maxt); mi[i] = mint; mx[i] = maxt; } int p = 0; for(int i=0;i<m;i++){ int mp = p; for(char j=l[i];j<=r[i];j++){ int tp = p; while(tp<s.size()&&s[tp]!=j) tp++; if(tp>=s.size()){ cyes; return; } mp = max(mp,tp+1); } p = mp; } cno; }
D:大意就是给出n长度的数组。你需要累加这些数。同时当你超过k时,你可以固定一个k以内的数,使得自身下降不会低于这个数。求获得最大的所确定的k,符合条件即可。
解法:很容易让人感觉是dp。刚开始我用dp求出来了最大值,然后想通过这个值来确定反推k,但是失败了。直觉告诉我,如果一个区间段累加最小,那么在这个区间段之前就需要将它固定。所以直接倒着推一下,当sum>=0时重置sum=0,然后每次计算最小区间,记录这个区间的前缀下标。最后将这个下标之前的数全部累加就是答案。
code:
void solve() { int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } ll sum = 0; ll mint = LNF; ll l=0; for(int i=n;i>=1;i--){ sum+=a[i]; if(sum<=mint){ l = i; mint = sum; } if(sum>=0) sum = 0; // cout<<sum<<endl; } // cout<<l<<endl; ll ok = l-1; ll ans = 0; for(int i=1;i<=ok;i++){ ans+=a[i]; } cout<<max(ans,0LL)<<endl; // ll maxt = 0;有点诈骗DP的感觉...... // for(int i=1;i<=n;i++){ // f[i][0] = f[i-1][0]+a[i]; // maxt = max(f[i][0],maxt); // f[i][1] = max(f[i-1][1]+a[i],max(maxt,f[i][0])); // } // s[n+1] = 0; // ll mint = LNF; // ll pos = n+1; // for(int i=n;i>=1;i--){ // s[i] = s[i+1]+a[i]; // if(s[i]<mint) mint = s[i],pos = i; // } // ll ans= 0; // for(int i=1;i<pos;i++){ // ans+=a[i]; // } // cout<<max(0LL,ans)<<endl; }