日常训练补题(第四周)

7-10 红色警报 - SMU 2024 spring 天梯赛2(补题) (pintia.cn)

题解:这题是一道暴力思维题

我们需要先统计一下最初的点的连通块

然后在一个个删除,每删除一次就跑一个并查集,在统计连通块的个数,然后对比前一次,看看连通块有没有变多即可

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}
int fa[N];
int find(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
void add(int x,int y)
{
    x=find(x),y=find(y);
    if(x!=y)
    {
        fa[x]=y;
    }
    return;
}
int x[N],y[N];
map<int,int> mp;
void solve()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        fa[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        int v,u;
        cin>>v>>u;
        add(v,u);

7-15 特殊堆栈 - SMU 2024 spring 天梯赛2(补题) (pintia.cn)

题解:这道题就是类似于模拟,但是我们需要处理中位数

思维一:用一个栈每次输入输出,记录这个栈里有没有东西,没有东西我们就需要返回错误

然后用对顶堆的思维去维护一下中位数即可   但是这里用优先队列不能用,因为不能删除我们插入的数,所以我们改用

multiset 这个函数相当于没有去重功能的set  然后用迭代器二分跑一下我们要输出元素的位置即可
输出就输出当个堆中间那个即可

思维二:还是这个中位数的问题,我们其实可以不用对顶堆
我们用一个vector然后删除的时候和上面一样二分删除 用迭代器
插入也是二分插入,二分插入让数组有序化然后正常输出中位数即可
void solve()
{
    int n;
    cin>>n;
    vector<int> a;
    stack<int> q;
    vector<int> ::iterator it;
    int r=0;

    for(int i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        int x;
        if(s=="Pop")
        {
            if(q.size()!=0) {
                it= lower_bound(a.begin(),a.end(),q.top());
                a.erase(it);
                cout<<q.top()<<endl;
                q.pop();

            }
            else
            {
                cout<<"Invalid"<<endl;
            }

        }
        if(s=="Push")
        {
            cin>>x;
            q.push(x);
            it = lower_bound(a.begin(),a.end(),x);
            a.insert(it,x);
        }
        if(s=="PeekMedian")
        {
            if(!q.empty())
            {
                int y=a.size();
                if(y%2) y++;
                y/=2;
                cout<<a[y-1]<<endl;
            }
            else
            {
                cout<<"Invalid"<<endl;
            }
        }
    }
}
signed main(){
//    std::ios::sync_with_stdio(false);
//    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 7-11 排座位 - SMU 2024 spring 天梯赛2 (pintia.cn)

题解:这道题少了3分,因为题目看漏了一个条件,就是朋友的朋友也是朋友,我直接判断的朋友的朋友不是朋友,所以少3分

这道题我们可以用并查集维护一下即可,就看看敌人有没有共同的祖先即可满分

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=9e3+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}

int a[N][N];
vector<int> b[N];
int fa[N];
int find(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=find(fa[x]);
}
void add(int x,int y)
{
    x=find(x),y=find(y);
    if(x!=y)
    {
        fa[x]=y;
    }
}

void solve()
{
    int n;
    cin>>n;
    int m;
    cin>>m;
    int k;
    cin>>k;
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        int x,y;
        int op;
        cin>>x>>y>>op;
        if(op==-1)
        {
            a[x][y]=-1;
            a[y][x]=-1;
        }
        else
        {
            a[x][y]=1;
            a[y][x]=1;
            add(x,y);
            b[x].push_back(y);
            b[y].push_back(x);
        }
    }
    while (k--)
    {
        int x,y;
        cin>>x>>y;
        if(a[x][y]==0)
        {
            cout<<"OK"<<endl;
        }
        else if(a[x][y]==1)
        {
            cout<<"No problem"<<endl;
        }
        else if(a[x][y]==-1)
        {
            int f=0;
            if(find(x)==find(y)) f=1;
            if(f)
            {
                cout<<"OK but..."<<endl;
            }
            else
            {
                cout<<"No way"<<endl;
            }
        }
    }

}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 7-13 肿瘤诊断 - SMU 2024 spring 天梯赛2 (pintia.cn)

题解:一道宽搜题目,我们开一个三维数组去记录一下 这个是一个有前 后 上 下 左 右  6个方向,我们每一次直接搜索一下6个方向即可,如果满足条件那么加上体积即可

注意人家是一个立体的有上面和下面  不单单一个平面 

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=9e3+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}
int dir[6][3]={{0,1,0},{0,-1,0},{0,0,-1},{0,0,1},{1,0,0},{-1,0,0}};
int a[70][1300][130];
int ans=0;
int vis[70][1300][130];
int n,m,l,t;
int bfs(int u,int x,int y)
{
    queue<int> q[3];
    vis[u][x][y]=1;
    q[0].push(u);
    q[1].push(x);
    q[2].push(y);

    int sum=1;
    while (!q[0].empty())
    {
        int uq=q[0].front();
        int xq=q[1].front();
        int yq=q[2].front();
        q[0].pop();
        q[1].pop();
        q[2].pop();
        for(int i=0;i<6;i++)
        {
            int uu=uq+dir[i][0];
            int xx=xq+dir[i][1];
            int yy=yq+dir[i][2];
            if(uu>=1 && uu<=l && xx>=1 && xx<=n && yy>=1 && yy<=m && vis[uu][xx][yy]!=1 && a[uu][xx][yy]==1)
            {
                sum++;
                q[0].push(uu);
                q[1].push(xx);
                q[2].push(yy);
                vis[uu][xx][yy]=1;
            }
        }
    }
    if(sum>=t)
    {
        return sum;
    }
    else return 0;
}
void solve()
{

    cin>>n>>m>>l>>t;
    for(int i=1;i<=l;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int z=1;z<=m;z++)
            {
                cin>>a[i][j][z];
            }
        }
    }
    for(int i=1;i<=l;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int z=1;z<=m;z++)
            {
                if(a[i][j][z]==1 && vis[i][j][z]!=1)
                {
                    ans+=bfs(i,j,z);
                }
            }
        }
    }
    cout<<ans<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}
7-9 哈利·波特的考试 - SMU 2024 spring 天梯赛3(补题) (pintia.cn)
题解:这个题当时缺了一个点,是一个判断0的点
首先我们直接floyd求各个点的最短路,然后在暴力去跑每一个点到其他点的距离找最大判断一下即可
#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}

int d[2000][2000];
int n,m;
vector<int> c[N];

void floyd()//一个贪心去找每一个节点的中间最优节点
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
}

void solve()
{

    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) d[i][j]=0;
            else d[i][j]=INF;
        }
    }
    for(int i=1;i<=m;i++)
    {
        int a,b,su;
        cin>>a>>b>>su;
        c[a].push_back(b);
        c[b].push_back(a);
        d[a][b]=su;
        d[b][a]=su;
    }

    int f=0;
    floyd();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            if(d[i][j]==INF) f=1;
        }
    }
    if(f)
    {
        cout<<0<<endl;
        return;
    }


    int k=0;
    int ans=INF;
    for(int i=1;i<=n;i++)
    {
        int sum=0;
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            sum=max(sum,d[i][j]);
        }
        if(sum<ans) {
            k=i;
            ans = min(ans, sum);
        }
    }
    cout<<k<<" "<<ans<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

7-8 连续因子 - SMU 2024 spring 天梯赛3(补题) (pintia.cn)

题解:暴力枚举即可

因为这个东西的长度最大不超过14,否则乘超过题目涉及范围

首先我们枚举长度,从2开始

判断从2开始乘超过n就结束

然后从3开始以此类推

然后符合条件记录一下头和尾,还有长度。输出即可

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e6+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}

bool pr(int x)
{
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0) return false;
    }
    return true;
}

void solve()
{
    int n;
    cin>>n;
    int si=0;
    int st=0;
    int en=0;
    if(pr(n))
    {
        cout<<1<<endl;
        cout<<n<<endl;
    }
    else
    {
        for(int i=2;i<= sqrt(n);i++)
        {
            int sum=1;
            for(int j=i;sum*j<=n;j++)
            {
                sum*=j;
                if(n%sum==0 && j-i+1>si)
                {
                    st=i;
                    si=j-i+1;
                    en=j;
                }
            }
        }
        cout<<si<<endl;
        for(int i=st;i<=en;i++)
        {
            cout<<i;
            if(i!=en) cout<<"*";
        }
    }
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 7-12 病毒溯源 - SMU 2024 spring 天梯赛3 (pintia.cn)

题解:这是一个树题

首先我们先存个图,注意这里存完要排个序,保证小的点在前面,这样跑出来的就是最小序列

然后我们跑树丛叶子结点向上跑 每一次记录最长的值

这里我们用一个数组存链

比如对于这个长链来说,根节点u当下标存的下一个节点,这样我们就可以靠根节点不断向下跑链上的数字了

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}

vector<int> su[N];
int gen[N];
int a[N];
int dfs(int u)
{
    int sum=0;
    a[u]=-1;
    for(int i=0;i<su[u].size();i++)
    {
        int x=su[u][i];
        int d=dfs(x);
        if(d>sum)
        {
            sum=d;
            a[u]=x;
        }
    }
    return sum+1;
}

void solve()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int k;
        cin>>k;
        for(int j=1;j<=k;j++)
        {
            int x;
            cin>>x;
            gen[x]=1;
            su[i].push_back(x);
        }
        sort(su[i].begin(),su[i].end());
    }
    int rr=0;
    for(int i=0;i<n;i++)
    {
        if(!gen[i])
        {
            rr=i;
        }
    }
    cout<<dfs(rr)<<endl;
    cout<<rr;
    while (a[rr]!=-1)
    {
        cout<<" "<<a[rr];
        rr=a[rr];
    }
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 7-12 这是二叉搜索树吗? - SMU 2024 spring 天梯赛2(补题) (pintia.cn)

题解:一道数据结构题

我们直接按照题目要求构建这个排序树,然后分别构建正常的和镜像的

然后在递归的去吧后序结果跑出来,如果后序里节点数不够那没结束不可行

我们先处理正常树

分左右子树去递归即可

 
while (i<=r && a[i]<a[l]) i++;
        while (j>l && a[j]>=a[l]) j--;
get(l+1,j);
get(i,r);

这样我们就可以建起来,每一次分成两堆,最后一个个按照左边插入成后序

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+10,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}
bool f;
int a[N];
vector<int> hou;
void get(int l,int r)
{
    if(l>r) return;
    int i=l+1,j=r;
    if(!f)
    {
        while (i<=r && a[i]<a[l]) i++;
        while (j>l && a[j]>=a[l]) j--;
    }
    else
    {
        while (i<=r && a[i]>=a[l]) i++;
        while (j>l && a[j]<a[l]) j--;
    }
    if(i-j!=1) return;
    get(l+1,j);
    get(i,r);
    hou.push_back(a[l]);
}
void solve()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    get(1,n);
    if(hou.size()!=n)
    {
        f= true;
        hou.clear();
        get(1,n);
    }
    if(hou.size()==n)
    {
        cout<<"YES"<<endl;
        for(int i=0;i<hou.size();i++)
        {
            cout<<hou[i];
            if(i!=hou.size()-1) cout<<" ";
        }

    }
    else cout<<"NO"<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

posted @ 2024-03-29 19:50  whatdo+  阅读(5)  评论(0编辑  收藏  举报