首页 > 其他分享 >CF2019

CF2019

时间:2024-10-01 09:11:43浏览次数:5  
标签:return int ll long mxn fx CF2019

CF2019

A.Max Plus Size

难度:红
弱智题。
奇数偶数分别判一遍。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,n,a[110],dp[110][110][2],ans1,ans2; 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n;
        ans1=ans2=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(i%2==1)ans1=max(ans1,a[i]);
            if(i%2==0)ans2=max(ans2,a[i]);
        }
        cout<<max(ans1+(n+1)/2,ans2+(n/2))<<'\n';
    }
    return 0;
}

B.All Pairs Segments

难度:橙
有点弱智题。
每个点计算贡献然后用一个map存起来。

#include<bits/stdc++.h>
#define ll long long
#define mxn 100010
using namespace std;
ll T,n,q,a[mxn]; 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        map<ll,ll> mp;
        cin>>n>>q;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++){
            ll b=i*(n-i+1)-1;
            mp[b]++;
            if(i<n&&a[i+1]-a[i]>1){
                b=i*(n-i);
                mp[b]+=a[i+1]-a[i]-1;
            }
        }
        for(int i=1;i<=q;i++){
            ll b;
            cin>>b;
            cout<<mp[b]<<' ';
        }
        cout<<'\n';
    }
    return 0;
}

C.Cards Partition

难度:黄
从 \(n\) 到 \(1\) 枚举,存在方案就输出。

#include<bits/stdc++.h>
#define ll long long
#define mxn 200010
using namespace std;
ll T,n,k,sum,mxa,a[mxn]; 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n>>k;
        sum=mxa=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            sum+=a[i];
            mxa=max(mxa,a[i]);
        }
        for(int i=n;i;i--){
            if((sum+k)/i>=mxa&&(i-sum%i)%i<=k){
                cout<<i<<'\n';
                break;
            }
        } 
    }
    return 0;
}

D.Speedbreaker

难度:黄
主要是一个区间交集存在性问题。考虑把 \([i-a[i]+1,i+a[i]-1]\) 当作一个区间。

#include<bits/stdc++.h>
#define ll long long
#define mxn 200010
using namespace std;
ll t,n,a[mxn],l[mxn],r[mxn];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++)
        l[i]=n+1,r[i]=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        l[a[i]]=min(l[a[i]],i*1ll);
        r[a[i]]=max(r[a[i]],i*1ll);
    }
    ll maxn=0,minn=n+1,lans=0,rans=n+1;
    bool flg=1;
    for(int i=1;i<=n;i++){
        if(!r[i])continue;
        minn=min(minn,l[i]);
        maxn=max(maxn,r[i]);
        if(maxn-minn>i-1)flg=0;
        if(rans<r[i]-i+1||lans>l[i]+i-1)flg=0;
        lans=max(lans,r[i]-i+1);
        rans=min(rans,l[i]+i-1);
    }
    if(flg)cout<<rans-lans+1<<'\n';
    else cout<<0<<'\n';
    return;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;
    while(t--)solve();
    return 0;
}

E.Tree Pruning

难度:黄-绿
机房巨佬说这题用虚树直接秒了。可蒟蒻连虚树是什么都不知道qwq
枚举每一个修剪到的深度,然后取最小值。如果是直接暴力的话时间复杂度 \(O(n^2)\),显然会炸。
设 \(mxdep_i\) 为每个点能到达的最大深度,\(dep_i\) 为每个点深度。于是每个点会在 \(dep_i\sim mxdep_i\) 处产生贡献。考虑前缀和优化。

#include<bits/stdc++.h>
#define ll long long
#define mxn 500010
using namespace std;
ll n,sum[mxn],dep[mxn],mxdep[mxn],ans;
vector<int> t[mxn];
void dfs(int u,int f){
    dep[u]=mxdep[u]=dep[f]+1;
    for(int i=0;i<t[u].size();i++){
        int v=t[u][i];
        if(v==f)continue;
        dfs(v,u);
        mxdep[u]=max(mxdep[u],mxdep[v]);
    }
    return;
}
void init(){
    ans=0;
    for(int i=1;i<=n;i++){
        t[i].clear();
        sum[i]=dep[i]=mxdep[i]=0;
    }
    return;
}
void solve(){
    cin>>n;
    init();
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        t[u].push_back(v);
        t[v].push_back(u);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++)
        sum[dep[i]]++,sum[mxdep[i]+1]--;
    for(int i=1;i<=n;i++){
        sum[i]+=sum[i-1];
        ans=max(ans,sum[i]);
    }
    cout<<n-ans<<'\n';
}
int main(){
	ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
	int t;
	cin>>t;
	while(t--)
		solve();
    return 0;
}

F.Max Plus Min Plus Size

难度:蓝-紫
第一题的...加强版?
首先,最大值一定为 \(a[n]\)。不然可以把 \(a[n]\) 旁边的删掉选 \(a[n]\)。
然后考虑从大到小枚举最小值。在每一次枚举完后打个标记,若两边的数标记过就用并查集合并。
注意最大值可能在合并的连通块中,需要用奇偶性判断。

#include<bits/stdc++.h>
#define ll long long
#define mxn 200010
#define pii pair<int,int> 
using namespace std;
ll T,n,f[mxn],st[mxn],sze[mxn];
ll jo[mxn][2],sum,ans,ok,vis[mxn];
pii a[mxn];
int fnd(int x){
    if(x==f[x])return x;
    return f[x]=fnd(f[x]);
}
int pd(int x){
    if(sze[x]%2==0){
        if(jo[x][0]||jo[x][1])return 1;
        else return 0;
    }
    else{
        if(st[x]%2==1){
            if(jo[x][1])return 1;
            else return 0;
        }
        else{
            if(jo[x][0])return 1;
            return 0;
        }
    }
    return 0;
}
void merge(int x,int y){
    int fx=fnd(x),fy=fnd(y);
    if(fx!=fy){
        sum-=(sze[fx]+1)/2+(sze[fy]+1)/2;
        ok-=pd(fx)+pd(fy);
        st[fx]=min(st[fx],st[fy]);
        jo[fx][0]|=jo[fy][0];
        jo[fx][1]|=jo[fy][1];
        sze[fx]+=sze[fy];
        sum+=(sze[fx]+1)/2;
        ok+=pd(fx);
        f[fy]=fx;
    }
    return;
}
void solve(){
    cin>>n;
    for(int i=1;i<=n+1;i++){
        f[i]=st[i]=i,sze[i]=1;
        jo[i][0]=jo[i][1]=0;
        vis[i]=0;
    }
    sum=ans=ok=0;
    for(int i=1;i<=n;i++){
        cin>>a[i].first;
        a[i].second=i;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
        if(a[i].first==a[n].first)
            jo[a[i].second][a[i].second&1]=1;
    for(int i=n;i;i--){
        int j=i;
        while(j&&a[j].first==a[i].first){//最大值必为a[n],枚举最小值
            int id=a[j].second;
            vis[id]=1;
            sum++;
            if(jo[id][0]||jo[id][1])ok++;
            if(vis[id-1])merge(id,id-1);
            if(vis[id+1])merge(id,id+1);
            ans=max(ans,a[n].first+a[i].first+sum-(ok<=0));
            j--;
        }
        i=j+1;
    }
    cout<<ans<<'\n';
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--)solve();
    return 0;
}

标签:return,int,ll,long,mxn,fx,CF2019
From: https://www.cnblogs.com/nagato--yuki/p/18437085

相关文章

  • CF2019D Speedbreaker
    题意Link一个数轴上有\(1,2,\dots,n\)共\(n\)个点。第\(1\)秒时,你将从其中一个点开始染色,称为初始点,之后第\(2,3,\dots,n\)秒,你每秒可以将一个被染色的点左边或右边的点染色。每个点有一个时间限制,必须要在\(a_i\)秒前(包含第\(a_i\)秒)被染色,问有多少个初始点可以将......
  • CF2019D. Speedbreaker 题解
    介绍一种另解,以下称“征服”为“拓展”。对于这些需要拓展,且拓展的时间有上界的题,我们通常都会有一个trick。那就是对于一个点\(x\),用它可以拓展到的点\(y\)的时间上界把\(x\)的时间上界继续缩小。用到这种trick的题有P9755[CSP-S2023]种树、[ABC304Ex]ConstrainedTop......
  • CF2019C Cards Partition
    涉及知识点:鸽巢原理,贪心前言唐诗题,赛时都已经想到了所有性质,以为要从数学方法上求解,却没想到就是个纯贪心题……题意Link给你一堆数,\(1,2,3,\dots,n\),分别有\(a[1],a[2],a[3],\dots,a[n]\)个,你还可以添加不超过\(k\)个数(当然这些数得是\(1\simn\)中的整数),你需要将它们......