首页 > 其他分享 >Codeforces div2 C题补题

Codeforces div2 C题补题

时间:2024-02-06 20:44:43浏览次数:35  
标签:pre suf int ll Codeforces long 补题 using div2

Codeforces div2 C题补题

1922 C. Closest Cities

C. Closest Cities

很容易看出,端点的两个城市的最近城市就是他的直接后继和直接前驱,而中间的城市的最近城市就是他前驱和后继中距离绝对值最小的那个,因此我们可以先预处理出每个城市对应的最近城市,用map存储。

然后因为区间可以从左向右走也可以从右向左走,因此我们可以求出其前缀后缀和,前缀和表示从左向右的花费总和,后缀和表示从右向左的花费总和,在求前缀后缀和的时候,下一个如果恰好是距离最近的城市,我们就贪心地直接花费1块钱直接去那,否则就花费其距离的绝对值。

这样的话我们在进行询问的时候直接\(pre[r]-pre[l]\)就可以\(O(1)\)求出l到r的最短距离了

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define int long long
using ull = unsigned long long;                                                                             
using ll = long long;
using i128 = __int128_t;
using pii = pair<int,int>;
using psi = pair<string,int>;
constexpr ll MOD = 1e9+7;
//-------------------------------------------------------->>>>>>>>>>
inline void solve(){
    int n;
    cin>>n;
    vector<int> a(n+1,0);
    map<int,int> nest;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    nest[1]=2;
    nest[n]=n-1;
    for(int i=2;i<n;i++){
        if(abs(a[i-1]-a[i])<abs(a[i+1]-a[i])){
            nest[i]=i-1;
        }else{
            nest[i]=i+1;
        }
    }
    vector<int> pre(n+1,0);
    pre[1]=0;
    for(int i=2;i<=n;i++){
        if(i==nest[i-1]){
            pre[i]=pre[i-1]+1;
        }else{
            pre[i]=pre[i-1]+abs(a[i]-a[i-1]);
        }
    }
    vector<int> suf(n+2,0);
    suf[n]=0;
    for(int i=n-1;i>=1;i--){
        if(i==nest[i+1]){
            suf[i]=suf[i+1]+1;
        }else{
            suf[i]=suf[i+1]+abs(a[i]-a[i+1]);
        }
    }
    int m;
    cin>>m;
    while(m--){
        int l,r;
        cin>>l>>r;
        if(l>r) cout<<suf[r]-suf[l]<<"\n";
        else cout<<pre[r]-pre[l]<<"\n";
    }
}
inline void prework(){
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout<<fixed<<setprecision(12);
    prework();
    int T=1; 
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

1895 C. Torn Lucky Ticket

C. Torn Lucky Ticket

从字符串的最大长度不超过5可以猜到一定是可以枚举长度的,我们可以先把每个字符串\(str_i\)的数位总和和长度记录下来,用map存储,然后枚举\(str_i\)看\(str_i\)能够与哪些字符串构成符合要求的数字,然后枚举\(str_i\)的长度cnt作为其左半部分,这样的话右半部分剩余的长度就是\(rem=str_i.size()-cnt\),需要补足的长度就是\(cnt-rem\),这样我们之前存储的map就有用了,我们可以根据其总和和长度判断是否存在,有几个这样的字符串合法,\(mp[\{cnt-rem,pre-(tot-pre)\}]\),pre是枚举到字符串前i个字符的数位总和,这样便可以获取数量,因为可以左右拼也可以右左拼,所以还要再反向处理一遍,注意的是,因为可以和自己拼,所以前后各走一遍会重复,所以当枚举长度等于字符串长度时,加一遍就行了。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define int long long
using ull = unsigned long long;                                                                             
using ll = long long;
using i128 = __int128_t;
using pii = pair<int,int>;
using psi = pair<string,int>;
constexpr ll MOD = 1e9+7;
//-------------------------------------------------------->>>>>>>>>>
inline void solve(){
    int n;
    cin>>n;
    vector<string> a(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    map<pii,int> tok;
    for(int i=0;i<n;i++){
        int tot=0;
        for(int j=0;j<a[i].size();j++){
            tot+=a[i][j]-'0';
        }
        tok[{a[i].size(),tot}]++;
    }
    int ans=0;
    for(int i=0;i<n;i++){
        int tot=0;
        for(int j=0;j<a[i].size();j++){
            tot+=a[i][j]-'0';
        }
        int cnt=0;
        int pre=0,suf=0;//pre从前向后,suf从后向前
        for(int j=0;j<a[i].size();j++){
            cnt++;
            pre+=a[i][j]-'0';
            suf+=a[i][a[i].size()-j-1]-'0';
            int rem=a[i].size()-cnt;
            ans+=tok[{cnt-rem,2*pre-tot}];
            if(!(j==a[i].size()-1)){//如果j=a.size,suf就不累计进去了
                ans+=tok[{cnt-rem,2*suf-tot}];
            }
        }
    }
    cout<<ans<<"\n";
}
inline void prework(){
    
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout<<fixed<<setprecision(12);
    prework();
    int T=1; 
    // cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

1904 C. Array Game

C. Array Game

分类讨论,双指针

可以发现,当\(m\ge 3\)时一定为0,因为可以随便选择两个数字处理两次得到两个相同的数,再将这两个数相减,就一定是0

当m=1时,直接\(O(n^2)\)枚举就行,因为n很小

当m=2时,先排序,再用双指针求最小值就行,之前用了\(map<int,vector<int>>\)存储,虽然也是\(O(n^2)\)复杂度,但会MLE。

注意要先把原数组扫一遍取最小值

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
using ull = unsigned long long;                                                                             
using ll = long long;
using i128 = __int128_t;
using pii = pair<int,int>;
using psi = pair<string,int>;
constexpr ll MOD = 1e9+7;
//-------------------------------------------------------->>>>>>>>>>
inline void solve(){
    int n,m;
    cin>>n>>m;
    vector<int> a(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    if(m>=3){
        cout<<0<<"\n";
        return;
    }
    int maxn=INF;
    if(m==2){
        int ans = INF;
        sort(all(a));
        for (int j = 0; j < n; j++){
            ans = min(ans, a[j]);
        }
        for (int j = 0; j < n; j++){
            int p = 0;
            for (int l = j + 1; l < n; l++){
                while (p < n){
                    if (a[p] < a[l] - a[j]){
                        p++;
                    } else {
                        break;
                    }
                }
                ans = min(ans, a[l] - a[j]);
                if (p > 0){
                    ans = min(ans, (a[l] - a[j]) - a[p - 1]);
                }
                if (p < n){
                    ans = min(ans, a[p] - (a[l] - a[j]));
                }
            }
        }
        cout << ans << "\n";
        return;
    }
    if(m==1){
        for (int j = 0; j < n; j++){
            maxn = min(maxn, a[j]);
        }
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                maxn=min(maxn,abs(a[j]-a[i]));
            }
        }
        cout<<maxn<<"\n";
        return;
    }
}
inline void prework(){
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout<<fixed<<setprecision(12);
    prework();
    int T=1; 
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

标签:pre,suf,int,ll,Codeforces,long,补题,using,div2
From: https://www.cnblogs.com/KrowFeather/p/18010281

相关文章

  • Codeforces Round 913 (Div. 3) G.
    题目链接G.把灯看成节点,灯之间的关系看成有向边得到基环树森林若节点的入度为0,那么它一定要用一次开关,这是可以确定的所以用拓扑,把这些确定贡献的节点删去然后就剩下了若干个环若环上有奇数个权值为1的节点,那么不可能全部关上对于环上一个打开的灯,它要么直接用自己的开关......
  • Codeforces Round 921 (Div. 1) 题解
    HelloAd-HocForces!A字符集为前\(k\)个小写字母,给定长度为\(m\)的字符串,求所有的长度为\(n\)的字符串是否是这个字符串的子串。(此处字串不连续)如果不是需要给出反例。\(1\len,k\le26\),\(1\lem\le1000\)。\(\sumn,\summ\le10^6\)sol.D1A就是神秘贪心,汗流浃背......
  • Codeforces Round 917 (Div. 2)
    https://codeforces.com/contest/1917A.LeastProduct*800给定整数数组,可以把数组中的数\(a_i\)改为\(0\sima_i\)中的任意整数,最小化所有数的乘积,在此基础上使操作次数最少讨论一下负数的个数和\(0\)的个数#include<bits/stdc++.h>usingnamespacestd;usingll......
  • left 3 Codeforces Round 913 (Div. 3)
    题目链接A.把同行同列除了起点都输出即可#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=2e5+10;voidsolve(){charc;inta;cin>>c>>a;for(inti=1;i<=8;i++){if(i==a)continue;cout<<c<......
  • CodeCraft-22 and Codeforces Round 795 (Div. 2)C. Sum of Substrings(分类讨论、贪
    感觉分类讨论的能有点弱。遇到复杂一点的分类讨论的题目,代码就写的巨长。首先观察到处在中间位置的1对答案的贡献是11,具体在中间哪个位置是没有关系的。只有两端的两个位置是比较特殊的\(1位置处的1对答案的贡献是10\)\(2位置处的1对答案的贡献是1\)所有我们考虑将最左端第一......
  • SMU Winter 2024 div2 ptlks的周报Week 2(1.29-2.4)
    这周学习到的知识点有斯特林数(F鸡数题!)F鸡数题!思路第二类斯特林数代码#include<bits/stdc++.h>#defineintlonglong#defineMOD1000000007usingnamespacestd;intn,m,f[100005],fi[100005];intqpow(inta,intn){ intans=1; while(n){ if(n&1){ ......
  • CodeForces 1918E ace5 and Task Order
    洛谷传送门CF传送门世纪难题。首先我们考虑先固定\(x\),比如让\(x=a_1\)(重复问\(1\)直到回答为=),那么此时我们可以知道任意一个\(a_i\)和\(a_1\)的大小关系(问一次\(i\)再问一次\(1\)),并且可以知道\(a_i\)的具体值。那么剩下的数被分成了两个集合,一个\(<a_1\)......
  • left 2 Codeforces Round 916 (Div. 3)
    题目链接A.遍历字符串,用map记录下每个字符出现的次数最后遍历26个字母,若出现了相应次数答案+1#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e5+10;voidsolve(){intn;cin>>n;strings;cin>>s;map<char,int>mp;......
  • 【解题报告】CodeForces523D:Statistics of Recompressing Videos
    CF523D解题报告CF523D先上结果:前两次语言选错了,编译一直不过(做这题是因为集训老师让我做我就做了,要不然我都快忘了我有CF账号了(思路省流:STL大法开一个小根堆存目前正在运行的服务器(也可以大根堆,但是存时间进去的时候存负的),如果有空机就直接处理,这个视频处理完的时间就......
  • Codeforces Round 734 (Div. 3)B2. Wonderful Coloring - 2(贪心构造实现)
    思路:分类讨论:当一个数字出现的次数大于等于k,那么最多有k个能被染色,当一个数字出现的次数小于k,南那么这些数字都可能被染色还有一个条件就是需要满足每个颜色的数字个数一样多,这里记出现次数小于k的所有数字的出现次数总和为sum,将所有这些数字排序后,前sum-sum%k个数字是都可以......