首页 > 编程语言 >“海康威视杯“ 2022年第十四届四川省大学生程序设计大赛 A

“海康威视杯“ 2022年第十四届四川省大学生程序设计大赛 A

时间:2022-10-09 18:13:16浏览次数:79  
标签:1000010 26 威视杯 int 海康 2022 define 我们 逆序

Adjacent Swapping

https://ac.nowcoder.com/acm/contest/42105/A
赛时想出来逆序对+贪心的做法 但是最后一小时心态不稳 想着必须开出两道题 调爆了
最后发现只改了一行就过了
首先我们可以贪心的将模式串构造出来
比如我们a出现两次 那我们肯定就有一个a在后面一半
我们可以将任何字母前一半次出现的构建出来 有些重复的就直接后移即可 贡献也可以直接计算出来
并且我们这样前一部分是不用动的 感觉这样的正确性显然
这样我们只用算后面一半串 s2 所需要的步数即可
这里我们可以用逆序对 感觉是个很典的操作
但是这个逆序对 是要根据模板串来规定谁大谁小 但是注意的是 我们要是有相同字母比如后面有两个a
我们是不用把他们算进贡献的 为了避免这个 我们对于每个组内的下标reverse一遍即可
这样组内就不会产生贡献 组外该贡献时还是有贡献的

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define pi acos(-1)
int t[1000010],n,d[1000010],q[1000010];
string s,s1,s2;
bool cmp(int x,int y){
    if(q[x]==q[y])return x<y;
    return q[x]<q[y];
}
int lowbit(int x){return x&-x;}
void add(int x,int c){
    while(x<=n/2){
        t[x]+=c;
        x+= lowbit(x);
    }
}
int getsum(int x){
    int res=0;
    while(x){
        res+=t[x];
        x-= lowbit(x);
    }
    return res;
}
void solve(){
    cin>>n;
    cin>>s;s=')'+s;
    vector<int>a(26);
    for(int i=1;i<=n;i++){
        a[s[i]-'a']++;
    }
    int t=0;
    for(int i=0;i<26;i++){
        a[i]/=2;
        if(a[i])t++;
    }
    vector<int>b(26),v;
    int ans=0,cnt=0;
    for(int i=1;i<=n;i++){
        b[s[i]-'a']++;
        if(b[s[i]-'a']==a[s[i]-'a']){
            t--;
            s1.push_back(s[i]);
            if(!t){
                for(auto c:v)ans+=i-c-cnt,cnt++;
                for(int j=i+1;j<=n;j++){
                    s2.push_back(s[j]);
                }
                break;
            }
        }else if(b[s[i]-'a']<a[s[i]-'a']){
            s1.push_back(s[i]);
        }else{
            s2.push_back(s[i]);
            v.push_back(i);
        }
    }
    vector<int>mp[26],c(26);
    for(int i=0;i<s1.size();i++){
        mp[s1[i]-'a'].push_back(i);
    }
    for(int i=0;i<26;i++)reverse(mp[i].begin(),mp[i].end());
    for(int i=0;i<26;i++){
        c[i]=mp[i].size()-1;
    }
    for(int i=0;i<s2.size();i++){
        q[i+1]=mp[s2[i]-'a'][c[s2[i]-'a']--];
    }
    for(int i=1;i<=n/2;i++)d[i]=i;
    sort(d+1,d+n/2+1,cmp);
    for(int i=1;i<=n/2;i++){
        add(d[i],1);
        ans+=i-getsum(d[i]);
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;t=1;
    while(t--){
        solve();
    }
    return 0;
}

标签:1000010,26,威视杯,int,海康,2022,define,我们,逆序
From: https://www.cnblogs.com/ycllz/p/16773154.html

相关文章