2022杭电多校第八场

1001.Theramore

易知,字符串的奇偶项之间不会互换,只需要奇偶分别排序即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
    vector<int>odd,even;
    string s;
    cin>>s;
    for( int i=0;i<s.size();i++){
        if(i%2) odd.push_back(s[i]-'0');
        else even.push_back(s[i]-'0');
    }
    sort(odd.begin(),odd.end());
    sort(even.begin(),even.end());
    for( int i=0;i<s.size();i++){
        if(i%2){
            cout<<odd[i/2];
        }
        else cout<<even[i/2];
    }
    cout<<"\n";
}
signed main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

1007.Darnassus

kruskal最小生成树算法
若使用暴力法,则共有n^2条边,时间复杂度过高。
可以考虑通过边的取值范围来限制问题的规模,由于每条边的长度至多为
n-1,因此|i-j||pi-pj|至少有一个小于sqrt(n-1)这样可以将问题的规模降至n*sqrt(n)再使用桶排序对所有的边进行排序,最后使用kruskal算法得出答案。

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
struct dsu
{
    const int n;
    vector<int>a;
    dsu( int n):n(n+1),a(n+1){
        for( int i=0;i<n+1;i++) a[i]=i;
    }
    //y向x合并
    void unite(int x, int y) {
        a[find(y)] = find(x);
    }
    int find(int u) {
        return a[u] == u ? a[u] : a[u] = find(a[u]);
    }
};
ll solve(){
    int n;
    cin>>n;
    vector<int>v1(n+1),v2(n+1);
    vector<vector<pair<int,int>>>val(n);
    dsu d(n+1);
    int cnt=0;
    for( int i=1;i<=n;i++){
        cin>>v1[i];
    }
    for( int i=1;i<=n;i++){
        v2[v1[i]]=i;
    }
    for( int i=1;i<=n;i++){
        for( int j=i+1;j<=n;j++){
            if(1ll*abs(i-j)*abs(i-j)>=n) break;
            int x=abs(i-j)*abs(v1[i]-v1[j]);
            if(x<n)
            val[x].push_back({i,j});

            x=abs(i-j)*abs(v2[i]-v2[j]);
            if(x<n)
            val[x].push_back({v2[i],v2[j]});
        }
    }   
    ll ans=0;
    for( int i=1;i<n;i++){
        for( auto it:val[i]){
            int x=it.first,y=it.second;
            if(d.find(x)!=d.find(y)){
                ans+=i;
                d.unite(x,y);
            }
        }
    }
    return ans;
    
}
signed main(){
    std::ios::sync_with_stdio(false);//消除输入输出缓存
    std::cin.tie(0);//解除cin与cout的绑定,加快速率。
    int t;
    cin>>t;
    while(t--){
        cout<<solve()<<"\n";
    }    
    // system("pause");
}

1008.Orgrimmar

求一棵树的最大分离集的大小,只需要分状态dp即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll solve(){
    int n;
    cin>>n;
    vector<vector<int>>g(n+1);
    for( int i=0;i<n-1;i++){
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<array<int,3>>dp(n+1);
    auto dfs=[&](auto self, int rt,int fa)->void{
        dp[rt][0]=dp[rt][1]=1;
        int x=1e9,y=0;
        int sum=0;
        for( auto it:g[rt]){
            if(it==fa) continue;
            else {
                self(self,it,rt);
                dp[rt][0]+=dp[it][2];
                x=min(x,dp[it][2]-dp[it][0]);
                sum+=dp[it][2];
                dp[rt][2]+=max({dp[it][0],dp[it][1],dp[it][2]});
            }
        }     
        dp[rt][1]+=max({sum,sum-x});             
         
    };
    dfs(dfs,1,0);
    return max({dp[1][0],dp[1][1],dp[1][2]});

}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int size(512<<20);  // 512M
    __asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
    // YOUR CODE
    int t;
    cin>>t;
    while(t--){
        cout<<solve()<<"\n";
    }
    exit(0);
}

1011.Stormwind

将一个矩形切割成若干个矩形,只需枚举长的方向上被切的数量,再计算宽上对应的被切割成的数量。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll solve(){
    ll n,m,k;
    cin>>n>>m>>k;
    ll ans=0;
    for( ll i=1;i<=n;i++){
        ll area=(n/i)*m;
        if(area<k) continue;
        ll j=min(m,area/k);
        while(j!=0&&(n/i)*(m/j)<k){
            j--;
        }
        if(j<=0) continue;
        ans=max(ans,i+j-2);
    }
    return ans;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        cout<<solve()<<"\n";
    }
    system("pause");

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值