2021-11-19周赛总结

A:

A (codeforces.com)

前几天桂林的签到题,那场我当了志愿者,有个队伍一分钟过了这道给我看傻了,然后我直接经典复刻,一分钟a了,就是3局两胜五局三胜,输出2n-1就行了

B:

Problem - 940E - Codeforces

题意:

给你一个数组和一个数c,要求你把这个数组分成若干连续子串,每个串内删掉最小的[k/c]个数(k为串的长度)问怎么样能让剩余数的和最大

思路:

首先要让剩下的数最多肯定尽可能多删除一些数,所以我们分出的每个区间的长度都要尽量是c的倍数,那我们再考虑区间长度为2c的时候,当区间长度为2c的时候从其中选出的两个最小值的和一定小于等于我从中间劈成两个长度为c的区间分别取最小值的和,理由:假设这个长为2c的区间最小值都在左侧,那我分成左右两块,右侧一定会出来一个比之前的两个最小值都大的数,假设最小值*两侧,那我劈开也是一样的。因此我们只需要考虑每次都把区间分为长度为c或者长度为1的即可(为什么长度为1:因为剩下的一定是长度小于c的区间,不会删除数,所以长度为一显得结论很简洁),剩下的就简单了,我们维护出每个长度为c的区间的最小值(单调队列),然后从中选出互不冲突的和最大的一些区间即可(dp)

这题朱爹之前跟我讲过,但是我直到比完朱爹过来跟我说思路我才想起来,主要是我也没细想,觉得e比较简单就跑去做e了。呜呜呜

 #include <bits/stdc++.h>
 using namespace std;
 #define ll long long
 ll x[100001];
 ll mn[100001]; 
 ll dp[100001];
 int main(){
     ll n,m;
     cin>>n>>m;
     ll all=0;
     for(int i=0;i<n;i++){
         cin>>x[i];
         all+=x[i];
     }
     deque<ll>q;
     //前面有几发单调队列写爆了(艹,fw),这里必须要存下标,不能存值,不然就会出现这个值明明已经不在区间内了,但是还被当成最小值计算
     for(int i=0;i<n;i++){
         while(!q.empty()&&x[q.back()]>x[i]){
             q.pop_back();
         } 
         q.push_back(i);
         if(q.front()<=i-m){
             q.pop_front();
         }
         mn[i]=x[q.front()];
     }
     for(int i=0;i<m;i++){
         dp[i]=0;
     }
     dp[m-1]=mn[m-1];
     ll ans=dp[m-1];
     for(int i=m;i<n;i++){
         //这个转移方程不会有人想不出来吧(,虽然我一开始都没想到用dp做
         dp[i]=max(dp[i-1],mn[i]+dp[i-m]);
         ans=max(ans,dp[i]);
     }
     cout<<all-ans<<endl;
     return 0;
 }

C:

60d96203192132ddf55f8ead09e2f322 (ppsucxtt.cn)

UVA上的题可还行,网站都崩了

题意:

给定左右边界,求区间内所有数总共出现了多少次零

思路:

思路个der,数位dp,oiwiki上的第一道例题,xswl根本没学,我以为是个数学问题想了半天,正好我这几周开dp了,等学到了再补上。

D:

Problem - J - Codeforces

大大大大模拟,题目贼长,不想看,所以没写

题意:给定一些定义变量的式子,计算占用的内存

有个地方很恶心,题目说round up to ,我百度翻译查出来是四舍五入,但是我是按向上取整写的(因为样例就是向上取整),然后过了

#include <bits/stdc++.h>
 using namespace std;
 #define ll long long
 ​
 int fun(string a){
     int pos1=a.find('[');
     int pos2=a.find(']');
     if(pos1==string::npos||pos2==string::npos){
         return 1;
     }else{
         string tem=a.substr(pos1+1,pos2-2);
         int ans=atoi(tem.c_str());
         return ans;
     }
 }
 ​
 int main(){
     int t;
     cin>>t;
     ll ca=1;
     while(t--){
         int n;
         cin>>n;
         ll ans=0;
         for(int i=0;i<n;i++){
             string a;
             cin>>a;
             string b;
             cin>>b;
             int num=fun(b);
             if(a=="int"){
                 ans+=num*4;
             }else if(a=="char"){
                 ans+=num*1;
             }else if(a=="bool"){
                 ans+=num*1;
             }else if(a=="long"){
                 string c;
                 cin>>c;
                 num=fun(c); 
                 if(b=="long"){
                     ans+=num*8;
                 }else if(b=="double"){
                     ans+=num*16;
                 }
             }else if(a=="__int128"){
                 ans+=num*16;
             }else if(a=="float"){
                 ans+=num*4;
             }else if(a=="double"){
                 ans+=num*8;
             }
         }
         printf("Case #%lld: ",ca++);
         if(ans%1024!=0){
             ans+=1024;
         }
         cout<<ans/1024<<endl;
     }
     return 0;
 }

Problem - G - Codeforces

垃圾错题,又喜提一发wa。

上一篇:Linux 命令中 which、whereis、locate 命令的用法。


下一篇:2021/11/19