SMU Winter 2024 div2 3rd

作者分享了一周的编程经历,包括差分优化、背包问题、拓扑排序、动态规划等算法的学习与应用,反思了在团队协作和解题技巧上的不足,计划挑战更偏重思维的题目。
摘要由CSDN通过智能技术生成


The Third Week

反思是知识的沉淀,智慧的启示,思维的升华。——泰戈尔

一、前言

周一打了牛客,额,我是队长,但实在是不理解三个人该怎么互相配合着打信息竞赛,幸好是一人一台电脑,大家各自选了几个擅长的模块的题再写,但配合也并不好,最后只ac了3题,大家都有点气馁。插句题外话,那个很厉害的第一去打div1了好像,还是超厉害,向他致敬。
周三又打了排位赛,做了这么多天的题目,这些题目属于我想一会能想出来的类型,还挺喜欢这个难度的,毕竟一直做不出来也是很有挫败感的,抽时间补题。另外下一次就又是牛客了。
新年快乐
周五排位赛,就我自己来说还算满意吧。


二、算法

1.差分优化

<1>(洛谷P3406)

一道蛮经典的差分,但我总感觉有点dp的意思,差分跟前缀和挺相近的,上周学完前缀和之后就去看差分了。
题解:
题目较长,大意是要去m个城市,每俩个城市间可以选择购买纸质单程票,或者买卡充值,可重复通过一个城市,问最少花多少钱。
剩下的就很简单了,一个差分的板子,可以用二维但是还没学会。
代码:

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n,m;
    cin>>n>>m;
    long long int p[100010];
    long long int q[100010];                //记录每段路的经过次数
    for(int i=1;i<=m;i++)cin>>p[i];
    int a[100010],b[100010],c[100010];
    int cf[100010];                         //用于差分数组
    for(int i=1;i<=n-1;i++){
        cin>>a[i]>>b[i]>>c[i];
    }
    for(int i=1;i<=m-1;i++){                //差分
        if(p[i]<=p[i+1]){
            cf[p[i]]+=1;
            cf[p[i+1]]-=1;
        }
        else {
            cf[p[i+1]]+=1;
            cf[p[i]]-=1;
        }
    }
    long long int sum=0;
    for(int i=1;i<=n-1;i++){
        q[i]=q[i-1]+cf[i];                   //前缀和
        sum+=min(a[i]*q[i],c[i]+b[i]*q[i]);  //取价格小的情况
    }                                        //贪心?
    cout<<sum;
    return 0;
}

2.背包

<1>(CF Gym102897F)

01背包+完全背包

3.拓扑排序

在一个有向图中找一个拓扑序列的过程称作拓扑排序。
先行关系具有可转递性,拓扑序列不是唯一的,甚至有可能不存在。

<1>(AOV)

事实上我只能勉强听懂并跟着up主走一遍
代码:

#include<bits/stdc++.h>
using namespace std;

typedef struct node{
    int adj;
    struct node *nextarc;
}arcNode;
typedef struct{
    string data;
    arcNode *firstArc;
}vexNode;
typedef struct{
    int n,e;
    vexNode adjlist[20];
}AdjGraph;

void createGraph(AdjGraph &g){
    cin>>g.n>>g.e;
    for(int i=0;i<g.n;i++){
        cin>>g.adjlist[i].data;
        g.adjlist[i].firstArc=NULL;
    }
    int u,v;
    for(int i=0;i<g.e;i++){
        cin>>u>>v;
        arcNode *s=new arcNode;
        s->adj=v;
        s->nextarc=g.adjlist[u].firstArc;
        g.adjlist[u].firstArc=s;
    }
}
int TopoSort(const AdjGraph &g){
    stack<int>s;
    int indegree[20]={0};
    arcNode *p;
    for(int i=0;i<g.n;i++){
        p=g.adjlist[i].firstArc;
        while(p){
            indegree[p->adj]++;
            p=p->nextarc;
        }
    }
    for(int i=0;i<g.n;i++){
        if(indegree[i]==0)s.push(i);
    }
    int count =0;
    int u;
    while(!s.empty()){
        u=s.top();
        s.pop();
        count++;
        p=g.adjlist[u].firstArc;
    }
    if(count<g.n)return 0;
    else return 1;
}
int main() {
    AdjGraph g;
    createGraph(g);
    if(TopoSort(g)==0)
        cout<<"\n";
    else cout<<"\n";
    return 0;
}

<2>(CF Gym102897G)

啥也不是没写出来,真的服气
1.拓扑排序(dfs)
2.度的思想

4.DP

<1>(洛谷P1359)

过年的时候帮朋友看的一道dp题,刚好巩固一下,就放上来了
代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[205][205];
    int n;
    int dp[205];
    cin>>n;
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            cin>>a[i][j];
            dp[i]=1e9;
        }
    }
    for(int i=n-1;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            dp[i]=min(dp[i],a[i][j]+dp[j]);
        }
    }
    cout<<dp[1];
    return 0;
}

5.二分算法

二分查找一直有一个很大的问题就是mid的+1,-1,特意去学习了一下。

int L=-1,R=n;
while(L+1!=R)
{
	int mid=L+R>>1;
	if(check()) L=mid;
	else R=mid;
}

6.其它

<1>(CF Gym102897D)

这题只有十行代码…那为什么我特意弄了个其它放这题呢?因为我当时俩个小时没看明白这题…但是好多人都ac了,不懂但大受震撼,后来都想放弃了,就随便交了一次忽然脑子就开窍了…引以为戒,似难非难的题很多人做出来了总有它的道理。太简单了直接放代码了。
代码:

#include<bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int n;
    cin>>n;
    string s[n];
    int t=0;
    for(int i=0;i<n;i++){
        cin>>s[i];
        t+=s[i].length();
    }cout<<t<<endl;
    return 0;
}

<2>(CF Gym102899K)

这题说实在的,当时确实不太会做行列式 了,题目所给的计算方法我也不会,真没办法做了,后来去对着线性代数做行列式,代码编写不难。
题解:
题意即题面,问题在于看不懂note的计算公式,直接当行列式算的。
代码:

#include<bits/stdc++.h>
using namespace std;

int main() {
    int l,r;
    cin>>l>>r;
    int ans;
    int min=10000000;
    for(int x=l;x<=r;x++){
        int value=1170*(21-x)+41194-(21-x)*728-52504;
        if(value<min){
            min=value;
        }
    }
    cout<<min<<endl;
    return 0;
}

三、总结

这周过年很懈怠,加油。很多算法都只是大概学了一下,不知道能不能很好的运用。这次最大的问题在很多题目看不出它本质,其它里面的俩道题都是这种情况,本来应该做的更好的。也许可以考虑做一些比较偏的题,不考算法板子考思维的那种。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值