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

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;
}
posted @   ycllz  阅读(141)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示