首页 > 其他分享 >牛客练习赛122题解A-D

牛客练习赛122题解A-D

时间:2024-03-02 23:23:40浏览次数:24  
标签:const int 题解 ll long 牛客 122 solve dp

牛客练习赛122

A.黑白配

代码:

#include <bits/stdc++.h>
using namespace std ;
const int MAXN=1e5+7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
#define endl "\n"

void solve(){
	int t,n;
    cin>>t>>n;
    int a[n+1];
    while(t--){
        int cnt1=0,cnt2=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]==0){
                cnt1++;
            }else{
                cnt2++;
            }
        }
        cout<<abs(cnt1-cnt2)<<endl;
    }
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t=1;
	
//	cin>>t;
	while(t--){
		solve();
	}
	
	return 0;
}

B.映射

思路:

数组a中的数只能对应一个b中的值,若对应了两个以上b中的值则No

代码:

#include <bits/stdc++.h>
using namespace std ;
const int MAXN=1e5+7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
#define endl "\n"

void solve(){
	int n;
    cin>>n;
    int a[n+1];
    int b[n+1];
    int c[n+1];
    memset(c,0,sizeof(c));
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        cin>>b[i];
    }
    for(int i=1;i<=n;i++){
        if(c[a[i]]!=0&&c[a[i]]!=b[i]){
            cout<<"No"<<endl;
            return ;
        }
        c[a[i]]=b[i];
    }
    cout<<"Yes"<<endl;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t=1;
	
	cin>>t;
	while(t--){
		solve();
	}
	
	return 0;
}

C.马走日

思路:

画图可知,n小于3或者m小于3时特判,n和m都等于3时为8,当n>=3并且m>=3时所有点都可到达

代码:

#include <bits/stdc++.h>
using namespace std ;
const int MAXN=1e5+7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
#define endl "\n"

void solve(){
	ll n,m;
    cin>>n>>m;
    ll ans;
    if(n<3||m<3){
        if(n==1||m==1){
            ans=1;
        }else if(n==2){
            ans=1+(m-1)/2;
        }else{
            ans=1+(n-1)/2;
        }
    }else if(n==3&&m==3){
        ans=8;
    }else{
        ans=n*m;
    }
    cout<<ans<<endl;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t=1;
	
	cin>>t;
	while(t--){
		solve();
	}
	
	return 0;
}

D.圆

思路:

题目求删除一些边的最小代价,可以反过来求选择一些边的最大价值,一些相交的边不能同时存在,那么就是区间dp的问题。
先将环拆分成链,链的长度为环的两倍,这样可以求点n-1、n-2……的区间;存储边,存储两次,例如x小于y时,存储x-y和y-(x+n),后者为y到第二圈的x的区间;根据题意,两条边不能交叉,一个端点只能有最多一条边;
开始区间dp,第一个for循环枚举终点i,第二个for循环枚举起点j,第三个for循环枚举起点所能到达的点v,若在区间范围内,这里的dp值为j-v的价值+区间(j+1)-(v-1)的值\(dp_{j+1,v-1}\)+区间(v+1)- i的值\(dp_{v+1,i}\)。
最后枚举起点1-n,范围为n,找到最大的区间值,就是最大价值,总数减最大价值就是最小代价。

代码:

#include <bits/stdc++.h>
using namespace std ;
const int MAXN=1e5+7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
#define endl "\n"

void solve(){
    int n,m;
    cin>>n>>m;
    ll sum=0;//所有边之和
    vector<vector<pair<int ,int > > > edge(2*n+1);
    for(int i=1;i<=m;i++){
        int x,y,w;
        cin>>x>>y>>w;
        if(x>y){
            int t=x;
            x=y;
            y=t;
        }
        sum+=w;
        edge[x].emplace_back(y,w);
        edge[y].emplace_back(x+n,w);//y到第二圈的x
    }
    vector< vector<ll> > dp(2 * n + 1,vector<ll>(2 * n + 1, 0ll));//初始化二维数组
    for(int i=1;i<=2*n;i++){//枚举区间终点
        dp[i][i]=0;
        for(int j=i-1;j>=1;j--){//枚举区间起点
            if(i-j+1>n){
                break;
            }
            dp[j][i]=dp[j+1][i];
            for(int k=0;k<edge[j].size();k++){//枚举起点能到达的点
                int v=edge[j][k].first;//边的到达点
                int w=edge[j][k].second;//边的价值
                ll cnt=w;
                if(v>i){//超出区间范围
                    continue;
                }
                if(j+1<v-1){
                    cnt+=dp[j+1][v-1];
                }
                if(v+1<i){
                    cnt+=dp[v+1][i];
                }
                dp[j][i]=max(dp[j][i],cnt);
            }
        }
    }
    ll cnt=0;
    for(int i=1;i<=n;i++){//枚举所有长为n的区间
        cnt=max(cnt,dp[i][i+n-1]);
    }
    ll ans=sum-cnt;
    cout<<ans<<endl;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	int t=1;
	
//	cin>>t;
	while(t--){
		solve();
	}
	
	return 0;
}

标签:const,int,题解,ll,long,牛客,122,solve,dp
From: https://www.cnblogs.com/beater/p/18049438

相关文章

  • 牛客练习赛122 F 括号匹配 费用流
    CF打多了很多题目中的性质都挖掘出来了,也想到了费用流。很难\(dp\)因为一组中三个括号留下来一个很难作为状态进行dp。由于对括号匹配还不熟悉以为是\(n^2\)的图就没写了,事实上应该是线性的建图。所以对于\(n=2000\)这个数据范围网络流是可以过的。设置源点\(S\)和汇点\(T\)。......
  • CF1934题解
    题解首先拜谢波叔呀,一眼看上去没思路,直到看见了四重循环,大彻大悟。Solution没什么好说的,暴力四重题意大意就是给你一个数,在1,3,6,10,15中取数,使取出的数等于输入的数,求出至少需要用多少个数。求数代码: for(longlongi=0;i<=2;i++){ for(longlongj=0;j<=1;j++){ for(lo......
  • AT_abc169_f Knapsack for All Subsets题解
    如果我们定义\(dp[i][j]\)表示对于前i个字符而言,其子集满足条件的个数。那4么对于一个位置i而言,要么选择它贡献要么不选择,所以\(dp[i][j]=dp[i-1][j-a[i]](j>=a[i])+dp[i-1][j]\),这是每一个\(f(i)\)的函数。然后我们加上所有的\(dp[i][k](i:1到n)ans+=dp[i][k......
  • CF1383A String Transformation 1 题解
    若某一位\(i\)上\(A_i>B_i\),则显然无解。否则,建立并查集,然后遍历字符串,若\(A_i,B_i\)不在一个集合就合并\(A_i\)与\(B_i\),直到只剩下一个集合,此时的合并总次数即为答案。为什么呢?因为将\(A_i,B_i\)合并的操作可以视为等价于将以\(A_i\)开头的连续若干个相同字符均改......
  • 「TFOI R1」Unknown Graph 题解
    这里是出题人题解。\(\text{SolutionOfProblemC:UnknownGraph.}\)题意还是很清晰的,这里就不再赘述题意了。首先如果没有\(q\)的限制,显然有一种贪心思想就是每个点每次选剩余入度最多的与之连边。但是因为限制,就无法保证贪心的正确性。那该怎么办呢?一个大提示:这题是......
  • P3200 [HNOI2009] 有趣的数列 题解
    P3200[HNOI2009]有趣的数列感性地,我们认为在按照数值从小到大填数时每个时刻所填的奇数位的个数\(x\)不小于所填偶数位的个数\(y\)。我们考虑如何证明这一点。性质1:每一个偶数位上的数都要大于它前面所有的数。这一点应当是显然的。性质2:每一个偶数位上的数都不小于它的下......
  • AT_nikkei2019_2_qual_d Shortest Path on a Line 题解
    我们发现,brute-force的复杂度的优化瓶颈主要在建图上。于是我们有一个巧妙的转化:因为所有满足\(L\leS,T\leR\)的所有边\((S,T)\)的长度均为\(C\)。然后题目要求的是\(1\simN\)的最短路。那么在边权相等的情况下,走到的点的编号一定越大越好。于是在所有点对\((......
  • AT_abc243_e [ABC243E] Edge Deletion 题解
    首先,我们可以得出一个结论:令点\(i,j\)之间的最短路径边权和\(dis_{i,j}\),若存在一个点\(k\),使得\(k\neqi\)且\(k\neqj\)且\(dis_{i,k}+dis_{k,j}=dis_{i,j}\),则连接\(i,j\)的边可以被删去。该结论的正确性是显然的,因为将连接\(i,j\)的边删去后,\(i,j\)之间的......
  • AT_arc083_b [ABC074D] Restoring Road Network 题解
    难度虚高,建议评橙/黄qwq。首先我们发现这是一道最短路问题,且\(N\le300\),于是采取floyd算法解决。具体地,我们分情况分类讨论。令我们当前枚举到的最短路径起点为\(i\),终点为\(j\),中转点为\(k\),输入的矩阵为\(dis\)。若\(dis_{i,j}>dis_{i,k}+dis_{k,j}\),则一定无......
  • P9184 [USACO23OPEN] Moo Language B 题解
    恶♂趣♂味♂大♂模♂拟♂。首先是构造语句部分:开始肯定是尽可能地多用上不及物语句和及物语句;接着,因为及物语句的单词数量一定比不及物语句多,所以贪心地尽可能多地将不及物语句改为及物语句;然后,为了增加语句长度,再次贪心地在及物语句中尽可能多地添加名词和逗号即可。......