西南民族大学 2024 天梯选拔赛(二)

西南民族大学 2024 天梯选拔赛(二)

L1-1

查看代码

void solve() {
    cout<<"yuan shen, qi dong!";
}

 

L1-2

思路:化简比较

查看代码
 void solve() {
    double n;
    cin>>n;
    double b=1/n;
    if(fabs(n-b)<eps)cout<<"=";
    else if(n<b)cout<<"<";
    else cout<<">";
}

 

L1-3

查看代码
 void solve() {
    double x;
    cin>>x;
    double ans;
    if(x<9)ans=2;
    else {
        ans=1+8/x;
    }
    cout<<fixed<<setprecision(2)<<ans;
}

 

L1-4

思路:注意读题

查看代码
 void solve() {
    double a,b,c,d;
    cin>>a>>b>>c>>d;
    auto P=[](double a,double b){
        double res=(a+b)/2;
        if(fabs(a-0.0)<eps||fabs(b-0.0)<eps)res/=2;
        else if(fabs(a-2.0)<eps&&fabs(b-2.0)<eps)res*=2;
        return res;
    };
    double ans=(P(a,b)+P(c,d))/2;
    cout<<fixed<<setprecision(6)<<ans;
}

 

L1-5

思路:仔细读题

路径已经给定了,便可以求出路径长度。一个灯源能扩散到的范围是2*(15-m)+1,求最少需要灯源即可

查看代码
 void solve() {
    int n,m;
    cin>>n>>m;
    int sum=1;
    vector<PII>ve(n);
    for(int i=0;i<n;++i){
        cin>>ve[i].first>>ve[i].second;
        if(i)sum+=abs(ve[i].first-ve[i-1].first)+abs(ve[i].second-ve[i-1].second);
    }
    if(m==0)cout<<0;
    else{
        int cnt=(15-m)*2+1;
        cout<<(sum+cnt-1)/cnt;
    }
}

 

L1-6

思路:代码内容为第一个main到最后一个return

查看代码
 void solve() {
    int n;
    cin>>n;
    string s;
    cin>>s;
    string t;
    cin>>t;
    auto a=t.find("main"),b=t.rfind("return");
    if(a==-1||b==-1){
        cout<<"wrong";
        return ;
    }
    b+=5;
    for(int i=2;i<t.size();++i){
        if(i-2>=a&&i<=b)continue;
//        if(i<a||i-2>b){
        if(t[i-2]==s[0]&&t[i-1]==s[1]&&t[i]==s[2]){
            t[i-2]='z',t[i-1]='x',t[i]='z';
        }
//        }
    }
    cout<<t;
}

 

L1-7

思路:贪心

分成m段连续数相当于取出m-1个差值,那就贪心取最大的

查看代码
 void solve() {
    int n,m,ans=0;
    cin>>n>>m;
    vector<int>a(n),g;
    for(int i=0;i<n;++i){
        cin>>a[i];
        if(i){
            g.push_back(a[i]-a[i-1]);
        }
    }
    sort(g.begin(),g.end(),greater<int>());
    ans=a[n-1]-a[0];
    for(int i=0;i<m-1;++i)ans-=g[i];
    cout<<ans;
}

 

L1-8

思路:其实求的是异或和,用前缀异或和求

查看代码
 void solve() {
    int n;
    cin>>n;
    vector<int>ve(n+1);
    for(int i=1;i<=n;++i){
        cin>>ve[i];
        ve[i]^=ve[i-1];
    }
    int m;
    cin>>m;
    while(m--){
        int l,r;
        cin>>l>>r;
        int ans=ve[r]^ve[l-1];
        cout<<ans<<'\n';
    }
}

 

L2-1

思路:模拟啦

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};



void solve() {
    int n,k;
    cin>>n>>k;
    vector<int>a(n);
    queue<int>q;
    stack<int>s,now;
    for(int i=0;i<n;++i){
        cin>>a[i];
    }
    for(int i=n-1;i>=0;--i)q.push(a[i]);
    vector<vector<int>>ve;
    vector<int>t;
    while(1){
        if(q.empty()) {
            if (now.size() >= 2) {
                vector<int>f;
                while(now.size()){
                    f.push_back(now.top());
                    now.pop();
                }
                ve.push_back(f);
            } else if (now.size() == 1) {
                t.push_back(now.top());
                now.pop();
            }
            if (!s.empty()) {
                while(s.size()){
                    q.push(s.top());
                    s.pop();
                }
            } else {
                break;
            }
        }
        int u=q.front();
        q.pop();
        if(now.empty())now.push(u);
        else{
            if(u>now.top()&&u-now.top()<=k){
                now.push(u);
            }else{
                if(s.empty()){
                    s.push(u);
                }else{
                    if(s.top()>now.top()&&s.top()-now.top()<=k){
                        now.push(s.top());
                        s.pop();
                    }
                    s.push(u);
                }
            }
        }
    }
    for(auto v:ve){
        for(auto u:v)cout<<u<<' ';
        cout<<'\n';
    }
    for(auto v:t)cout<<v<<' ';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L2-2

思路:dfs

由于每种材料的等级最高100,枚举所有等级花费即可。然后就是dfs跑需要的合成材料

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
int x,m;
vector<int>id(N);
vector lev(3,vector<int>(105,0));
vector<PII>ve[N];

int dfs(int u){
//    if(ve[u].empty())return 0;
    int sum=0;
    for(auto [v,d]:ve[u]){
        if(!ve[v].empty())sum+=dfs(v);
        sum+=lev[id[v]][d];
    }
    return sum;
}

void solve() {
    cin>>x>>m;
    for(int i=0;i<m;++i){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        ve[a].push_back({b,d});
        id[b]=c-1;
    }
    lev[0][2]=1;
    for(int i=3,p=1;i<=100;++i,p++){
        lev[0][i]=lev[0][i-1]+p;
    }
    lev[1][2]=1;
    for(int i=3,p=2;i<=100;++i,p+=2){
        lev[1][i]=lev[1][i-1]+p;
    }
    lev[2][2]=1;
    for(int i=3,p=5;i<=100;++i,p+=5){
        lev[2][i]=lev[2][i-1]+p;
    }
    int ans=dfs(x);
    cout<<ans;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L2-3

思路:由于最多9位,考虑从数的状态求贡献。对于Si+Sj中的分割线可以在Si或Sj,那分别枚举每个数在Si和Sj的贡献。若一个数在Si,那就考虑所有分界线的情况(最多9种,因为最多9位),知道了分界线就可以求出另一半的各个位数之和,这里预处理出所有各个位数之和的个数,直接统计贡献即可。在Sj同理。还有一个条件是长度为偶数,那就把所有数按长度奇偶分类,统计贡献的时候只需要统计长度奇偶性相同的。

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};


void solve() {
    int n;
    cin>>n;
    vector<string>ve(n);
    vector<int>sum(n);
    vector<vector<int>>g(2,vector<int>(100));
    auto P=[](string s){
        int c=0;
        for(int i=0;i<s.size();++i)c+=s[i]-'0';
        return c;
    };
    for(int i=0;i<n;++i){
        cin>>ve[i];
        int c=P(ve[i]);
        g[ve[i].size()%2][c]++;
        sum[i]=c;
    }
    int ans=0;

    for(int i=0;i<n;++i){
        string c=ve[i];
        int p=c.size()%2;
        int l=0;
        for(int j=0;j<c.size();++j){
            l+=c[j]-'0';
            int r=sum[i]-l;
            if(l>r)ans+=g[p][l-r];
        }
        int r=0;
        for(int j=c.size()-1;j>0;--j){
            r+=c[j]-'0';
            l=sum[i]-r;
            if(l<r)ans+=g[p][r-l];
        }
    }
    cout<<ans;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L2-4

思路:bfs+贪心

首先贪心的想,先遍历权值小的位置。如果遇到强化剂,那直接加上权值,并令其权值为0,所以用{权值,x,y}来存储,跑一遍bfs即可

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};

struct E{
    int x,y,s;
    bool operator<(const E&e)const{
        return s>e.s;
    }
};

void solve() {
    int n,m,x,y,t;
    cin>>n>>m>>x>>y>>t;
    vector ve(n+1,vector<int>(m+1)),is(n+1,vector<int>(m+1)),st(n+1,vector<int>(m+1));
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)cin>>ve[i][j];
    for(int i=0;i<t;++i){
        int a,b;
        cin>>a>>b;
        is[a][b]=1;
    }
    priority_queue<E>q;
    st[x][y]=1;
    q.push({x,y,ve[x][y]});
    int ans=0;
    while(q.size()){
        auto [xx,yy,d]=q.top();
        q.pop();
        if(d<=ans||(x==xx&&y==yy)){
            ans+=d;
        }else break;
        for(int i=0;i<4;++i){
            int x1=xx+dx[i],y1=yy+dy[i];
            if(x1<0||x1>n||y1<0||y1>m||st[x1][y1])continue;
            if(is[x1][y1]){
                ans+=ve[x1][y1];
                q.push({x1,y1,0});
            }else q.push({x1,y1,ve[x1][y1]});
            st[x1][y1]=1;
        }
    }
    cout<<ans;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L3-1

思路:dp

根据题目所求,首先用f[i][j]表示前i个数分成j组的最大值,且若选第i个数,第i个数为第j组的最后一个

若不选第i个数:f[i][j]=f[i-1][j]

若选第i个数:f[i][j]=max(f[i][j],f[i-m][j-1]+sum{i-m+1,i} )

这里用前缀和求区间和

求具体方案的话,考虑倒着取,选取最优情况一定是满足 f[i][j]=max(f[i][j],f[i-m][j-1]+sum{i-m+1,i} ) ,那就可以枚举i,找到所有组别的最后一个数

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=5e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};


void solve() {
    int n,m,k;
    cin>>n>>m>>k;
    vector<int>p(n+1),pre(n+1);
    for(int i=1;i<=n;++i){
        cin>>p[i];
        pre[i]=pre[i-1]+p[i];
    }
    vector<vector<int>>f(n+1,vector<int>(k+1));
    for(int i=1;i<=n;++i){
        for(int j=1;j<=k;++j){
            f[i][j]=max(f[i][j],f[i-1][j]);//buxuan
            if(i-m>=0){
                f[i][j]=max(f[i][j],f[i-m][j-1]+(pre[i]-pre[i-m]));
            }
        }
    }
    cout<<f[n][k]<<'\n';
    vector<PII>ans;
    int t=k;
    for(int i=n;i>=m&&t>0;t--){
        while(t>0&&f[i][t]!=f[i-m][t-1]+pre[i]-pre[i-m]){
            i--;
        }
        ans.push_back({i-m+1,i});
        i-=m;
    }
    std::reverse(ans.begin(), ans.end());
    for(auto [x,y]:ans)cout<<x<<' '<<y<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

 

L3-2

思路:

dfs序(dfn)为是一棵树的每个节点在dfs中的进出栈的时间序列

将整棵树用dfn表示,相当在一维的序列上处理。一个节点的子树便可以由一段连续的dfn表示,相当于在一维序列上求区间和。修改的话找到该节点所在的dfn进行单点修改即可,用树状数组或线段树求

查看代码
 #include<bits/stdc++.h>
using namespace std;
#define int long long
//#define int __int128
#define double long double
typedef pair<int,int>PII;
typedef pair<string,int>PSI;
typedef pair<string,string>PSS;
const int N=1e6+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353;
const int MAXN=1e8+5;
const double eps=1e-12;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};

int c[N],n,m;
int lowbit(int x){
    return x&-x;
}
int getsum(int x){
    int ans=0;
    while(x>0){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
void add(int x,int k){
    while(x<=n){
        c[x]+=k;
        x+= lowbit(x);
    }
}
int get(int l,int r){
    return getsum(r)-getsum(l-1);
}
vector<vector<int>>g;
vector<int>to,l,r;
int idx=0;
void dfs(int u){
    to[u]=++idx;
    l[u]=idx;
    for(auto v:g[u]){
        dfs(v);
    }
    r[u]=idx;
}
vector<int>ve;
void solve() {
    cin>>n>>m;
    ve=vector<int>(n+1);
    for(int i=1;i<=n;++i){
        cin>>ve[i];
    }
    g=vector<vector<int>>(n+1);
    to=l=r=vector<int>(n+5);
    for(int i=2;i<=n;++i){
        int x;
        cin>>x;
        g[x].push_back(i);
    }
    dfs(1);
    for(int i=1;i<=n;++i)add(to[i],ve[i]);
    while(m--){
        int op,a,x;
        cin>>op;
        if(op==1){
            cin>>a>>x;
            add(to[a],x);
        }else{
            cin>>a;
            cout<<get(l[a],r[a])<<'\n';
        }
    }
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
//    cin>>t;
//    init();
    while(t--){
        solve();
    }
    return 0;
}

L3-3

posted @ 2024-03-10 00:01  bible_w  阅读(6)  评论(0编辑  收藏  举报