Codeforces Round #804 (Div. 2) && Codeforces Round #802 (Div. 2) A~D

802

A

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n,m;cin>>n>>m;
        int sum=0;
        for(int i=1;i<=m;i++)sum+=i;
        for(int i=2;i<=n;i++){
            sum+=i*m;
        }
        cout<<sum<<endl;
    }
    return ~~(0^_^0);
}

B

赛时我的写的1834ms 我以为不是正解 刚刚看了一下就是正解 可能是我的高精常数太大了???

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
bool cmp(vector <int> &A,vector <int> &B){ // 判断是否A > B
    if(A.size() != B.size()) return A.size() > B.size(); // 如果A、B长度不相同,长度长的那个数大
    for(int i = A.size() - 1;i >= 0;i --){ // 否则就要从最高位开始看(因为执行这个函数前,A和B数组都已经倒序,所以这里要从后往前看)
        if(A[i] != B[i]) return A[i] > B[i]; // 如果A的当前位和B的当前位不相等,当前位大的更大
    }
    return true; // 如果A、B数组都相等,这里可以直接返回true,当然也可以直接输出0
}
vector <int> sub(vector <int> &A,vector <int> &B){ // A - B
    int t = 0; // 每一位上相减得到的数
    vector <int> C; // 最后的答案
    for(int i = 0;i < A.size();i ++){ // 遍历一遍,和高精度加法不一样的是,只要遍历完A就行了,因为这里A肯定比B长
        t = A[i] - t; // t要等于A的当前位减掉自己,因为上一位有可能出现借位的情况
        if(i < B.size()) t -= B[i]; // 如果没有遍历完B,那么t减掉B的当前位
        C.push_back((t + 10) % 10); // 更新C数组
        // 这里如果没有借位,(t + 10) % 10就刚好等于t
        // 如果这里有借位,(t + 10) % 10就会借一个10下来
        if(t < 0) t = 1; // 如果t < 0,说明不够减,需要借位,把t赋值为1,就是在下一次执行中,A的当前位会减掉t
        else t = 0; // 否则够减,赋值为0,不用借位
    }
    while(C.size() > 1 && C.back() == 0) C.pop_back(); // 删除前导0
    return C; // 返回答案
}
signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        string a;cin>>a;
        if(a=="1"){
            cout<<1<<endl;
        }else{
            string b="1";
            if(a[0]=='9'){
                for(int i=2;i<=n;i++)b=b+'1';
            }else{
                for(int i=2;i<=n;i++)b=b+'0';
            }
            b=b+'1';
            vector <int> A,B; // 两个数,因为减法是从最低位开始减,我们可以把两个数倒过来
            for(int i = a.size() - 1;i >= 0;i --) A.push_back(a[i] - '0'); // 把a数组到过来存入A,记得a是string类型的数组,要减去'0'让它变成数字
            for(int i = b.size() - 1;i >= 0;i --) B.push_back(b[i] - '0'); // 把b数组倒过来存入B
            if(cmp(A,B)){ // 如果A > B
                auto C = sub(A,B); // 那么可以直接相减
                for(int i = C.size() - 1;i >= 0;i --)cout<<C[i];
            }
            else{ // 否则A < B,需要计算-(B - A)
                auto C = sub(B,A); // 计算B - A
                for(int i = C.size() - 1;i >= 0;i --)cout<<C[i];
            }
            cout<<endl;
        }
    }
    return ~~(0^_^0);
}

C

这种区间+-已经很习惯性的考虑前缀和或者是差分了吧
我们可以把题干种三种操作就转化为:1.d1--&&di++ 2.di++ 3.d1++
我们先贪心的把所有第一种操作做完 剩下的就只有第二三种操作了
最后别忘了记录a1的值 再加上去就行了

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        vector<int>a(n+1);
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        int ans=0,sum=a[1];
        for(int i=2;i<=n;i++){
            int b=a[i-1]-a[i];
            ans+=abs(b);
            if(b>0)sum-=b;
        }
        ans+=abs(sum);
        cout<<ans<<endl;
    }
    return ~~(0^_^0);
}

D

一眼二分&&dp 没啥好说的

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
        int n;cin>>n;
        vector<int>f(n+1);//f[i]表示前i个桶至少要的时间
        vector<int>a(n+1);
        vector<int>s(n+1);
        for(int i=1;i<=n;i++)cin>>a[i],s[i]=s[i-1]+a[i];
        f[1]=a[1];
        for(int i=2;i<=n;i++){
            f[i]=max(f[i-1],(s[i]-1)/i+1);
        }
        vector<int>v;//每根管子对应的时长
        for(int i=1;i<=n;i++){
            v.push_back(max(f[i],(s[n]-1)/i+1));
        }
        int q;cin>>q;
        while(q--){
            int x;cin>>x;
            if(lower_bound(v.begin(),v.end(),x,greater<>())!=v.end()){
                cout<<lower_bound(v.begin(),v.end(),x,greater<>())-v.begin()+1<<endl;
            }else cout<<-1<<endl;
        }
    return ~~(0^_^0);
}

A

不懂 猜的奇数无解 偶数 随便构造构造就有了

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        if(n%2){
            cout<<-1<<endl;
        }else{
            cout<<0<<' '<<n/2<<' '<<n/2<<endl;
        }
    }
    return ~~(0^_^0);
}

B

咋又是构造 随便观察一下样例就发现了

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n,m;cin>>n>>m;
        int a[5]={1,0,0,1};
        int b[5]={0,1,1,0};
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(i/2%2==0){
                    cout<<a[(j-1)%4]<<' ';
                }else if(i/2%2){
                    cout<<b[(j-1)%4]<<' ';
                }
            }
            cout<<endl;
        }
    }
    return ~~(0^_^0);
}

C

简而言之 就是维护一个区间 要是后一个点在区间内就可以随便放 然后还要减掉前面的数 否则就更新区间

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;
        cin >> n;
        int a[n + 1];
        int pos[n + 1];
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            pos[a[i]] = i;
        }
        int l = pos[0], r = pos[0];
        int ans = 1;
        for (int i = 1; i < n; i++) {
            if (pos[i] < l)
                l = pos[i];
            else if (pos[i] > r)
                r = pos[i];
            else
                ans = ans * (r - l + 1 - i) % mod;
        }
        cout << ans << endl;
    }
    return ~~(0^_^0);
}

D

是个dp吧 能看出来 但是最开始想的肯定都是n3的
我们考虑一个性质:
当一个数想要连续时 当且仅当他们相邻 或者相隔区间长度为偶数并且众数不大于n/2 这个很好想
状态表示:f[i]表示以ai为结尾的最长max 我们通过枚举f[i]并且后面区间可以消除 就可以get max
状态计算和n3做法一样枚举每一个前面的i即可
因为有了这个性质 所以说我们可以固定ai 然后少枚举一维

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
//#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        vector<int>a(n+1);
        for(int i=1;i<=n;i++)cin>>a[i];
        int w[n+10][n+10];
        memset(w,0,sizeof w);
        vector<int>t(n+1);
        for(int i=1;i<=n;i++){
            int mx=-1;for(int j=1;j<=n;j++)t[j]=0;
            for(int j=i;j<=n;j++){
                t[a[j]]++; mx=max(mx,t[a[j]]);
                if(mx<=((j-i+1)>>1)&&((j-i)&1)) w[i][j]=1; //区间长度为偶数并且众数不超过n/2
            }
        }
        vector<int>f(n+2);
        f[1]=1;
        for(int i=2;i<=n;i++)w[1][i-1]?f[i]=1:f[i]=-inf;
        for(int i=1;i<=n;i++){
            for(int j=i-1;j>=1;j-=2){
                if(j==i-1&&a[i]==a[j])f[i]=max(f[i],f[j]+1);//间隔区间长度为0时
                else if(a[i]==a[j]&&w[j+1][i-1])f[i]=max(f[i],f[j]+1);
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(w[i+1][n]||i+1>n)ans=max(ans,f[i]);
        }
        cout<<ans<<endl;
    }
    return ~~(0^_^0);
}
posted @ 2022-08-10 19:19  ycllz  阅读(36)  评论(0)    收藏  举报