Codeforces Round #560 (Div. 3) A-F解题报告

Codeforces Round #560 (Div. 3) A-F解题报告_第1张图片
在这里插入图片描述
现场赛三题,先吐槽下。c意识到贪心太晚,d被卡坑点,e会做了发现时间不够,f我觉得不假啊,补题的时候一直wa。

比赛一开始,读题有点慢,读懂后A题,就开始写。B题在纠结用multiset还是优先队列,其实3分钟就写完了,觉得不会这么简单,稳了一手才交。C题,没有一眼秒就去看了D题,发现D题读不懂,才开始想C。发现不用那么复杂啊,直接贪心。比赛结束20分钟前一直在怼D,被卡坑点了好烦,E题读了下,找到了权值剩5分钟,急着写,最后一分钟放弃了。

A题:写了个小小的模拟 稳了一下上交。

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn =2e5+5;

int a[maxn];

int main(){
    IO;
    int n,x,y;cin>>n>>x>>y;
    string s;cin>>s;
    forn(i,n) a[i] = s[i]-'0';
    int cnt = 0,ans = 0;
    for(int i=n-1;i>=0;i--){
        cnt++;
        if(cnt==y+1){
            if(!a[i]) ans++;
            break;
        }
    }
    cnt = 0;
    for(int i=n-1;i>=0;i--){
        cnt++;
        if(cnt==y+1){
            continue;
        }
        if(cnt==x+1) break;
        if(a[i]) ans++;
    }
    cout <<ans<<'\n';
    return 0;
}

B题:用的multiset

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

multiset<int>s;

int main(){
    IO;
    int n;cin>>n;
    forn(i,n){
        int x;
        cin>>x;
        s.insert(x);
    }
    int ans = 0,cnt = 1;
    for(auto x:s){
        //cerr<
        if(cnt<=x){
            cnt++,ans++;
        }
    }
    cout <<ans<<'\n';
    return 0;
}

C题贪心

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn =2e5+5;

int main(){
    IO;
    int n;
    string s;cin>>n>>s;
    int ans = 0,cnt = 1;
    vector<char>a;
    forn(i,n){
        if(!(cnt&1)){
            if(a.back()==s[i]){
                ans++;
                continue;
            }
        }
        cnt++;
        a.push_back(s[i]);
    }
    if(a.size()&1){
        ans++;a.pop_back();
    }
    cout<<ans<<'\n';
    if(!a.empty()){
        for(auto x:a) cout<<x;
    }
    cout<<'\n';
    return 0;
}

D题再检测因子是否正确时,竟然循环跑到了longlong让我重新定义了复杂度

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn  = 500;

ll a[maxn];

int main(){
    IO;
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        ll res = 1;
        forn(i,n) cin>>a[i];
        sort(a,a+n);
        forn(i,n){
            res = res/__gcd(a[i],res)*a[i];
        }
        if(n&1) res = a[n/2]*a[n/2];
        if(res>(1ll<<40)){
            cout<<-1<<'\n';
            continue;
        }
        ll z = floor(sqrt(res)+0.5);
        int cnt = 0;
        for(ll i=2;i<=z;i++){
            if(res%i==0){
                cnt++;
                if(i*i!=res) cnt++;
            }
        }
        if(cnt!=n) cout<<-1<<'\n';
        else cout<<res<<'\n';
    }
    return 0;
}

E题:我觉得好题
思路: 我们来看一下a数组被计算的次数,也就是它的贡献。
对于1 2 3 4 5,我们发现,1被计算15次,2被计算24次,3被计算33次,4被计算42次,5被计算51次。
为什么呢?因为每一个位置的贡献和l-r区间有关。只要被包含在那个区间就计算一次。
所以每个位置的权值是i+1
n-i
小学奥数学过,一个大的数×一个小的数相比两个数大小接近是更小的
所以a数组大小×权值排序
b数组逆排序
代码:

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;
const int mod = 998244353;
ll a[maxn],b[maxn],c[maxn];

int main(){
    IO;
    int n;cin>>n;
    forn(i,n){
        cin>>a[i];
        a[i]*=1ll*(i+1)*(n-i);
    }
    forn(i,n) cin>>b[i];
    sort(a,a+n);
    sort(b,b+n);
    reverse(b,b+n);
    ll ans = 0;
    forn(i,n) (ans+=a[i]%mod*b[i]%mod)%=mod;
    
    cout<<ans<<'\n';
    return 0;
}

F题:我wa了,我觉得不假啊
—更:没有假,我把输入的顺序读错题了
Codeforces Round #560 (Div. 3) A-F解题报告_第2张图片

#include 
using namespace std;
#define forn(i,n) for(int i=0;i
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;
int n,m,sum = 0;
pair<int,int>b[maxn];//天数,第几个
bool vis[maxn];
vector<int>a(maxn),aa(maxn),e[maxn<<2];

bool judge(int mid){
    memset(vis,0,sizeof(vis));
    forn(i,mid+1) e[i].clear();
    forn(i,m)if(!vis[b[i].second]&&b[i].first<=mid){
        e[b[i].first].push_back(b[i].second);
        vis[b[i].second] = 1;
    }
    int cnt = 0,t = sum;
    for1(i,mid){
        cnt++;
        if(!e[i].empty()){
            for(auto x:e[i]){
                int z = min(a[x-1],cnt);
                cnt-=z;
                t-=z;
            }
        }
    } 
    return cnt>=t*2;
}

int main(){
    IO;
    cin>>n>>m;
    forn(i,n){
        cin>>a[i];sum+=a[i];
    }
    forn(i,m) cin>>b[i].first>>b[i].second;
    sort(b,b+m);
    reverse(b,b+m);
    int l = 1,r = sum<<1,ans = 0;
    while(l<=r){
        int mid = l+r>>1;
        if(judge(mid)){
            ans = mid;
            r = mid-1;
        }   
        else l = mid+1;
    }
    cout <<ans<<'\n';
    return 0;
}

你可能感兴趣的:(icpc题解,cf)