Codeforces Round 96 (Rated for Div. 2)E. String Reversal(树状数组求逆序对)

Posted 小时のblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round 96 (Rated for Div. 2)E. String Reversal(树状数组求逆序对)相关的知识,希望对你有一定的参考价值。

传送门

题目大意:有初始字符串和目标字符串,目标字符串是初始字符串的反转。

每一步可交换相邻两个字符,求从初始字符串到目标字符串的最小步数。

题解:

若初始字符串为abcde,则反转后为edcba。用数组下标表示为初始字符串12345,反转后为54321。

反转后的串的逆序对个数就是从初始串到目标串需要交换的相邻字符的个数。

关键是如果初始字符串中有重复,如aaaza,反转后为azaaa。

用数组下标表示为12345,反转后为14235更优。

14235的逆序对个数就是12345交换相邻元素的步数。

树状数组求逆序对

 

写题解时突闻吹风机被导员收走的噩耗

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
 
#define N 200002
 
int n;
 
char s[N];
char t[N];
int c[N];
int tr[N];
long long res;
queue<int>a[30];
 
int lowbit(int x)
{
    return x&(-x);
}
 
void add(int x,int v)
{
    for(int i=x;i<=n;i+=lowbit(i))
    {
        tr[i]+=v;
    }
}
 
int getsum(int x)
{
    int tmp=0;
    for(int i=x;i>=1;i-=lowbit(i))
    {
        tmp+=tr[i];
    }
    return tmp;
}
 
int main()
{
    scanf("%d",&n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
    {
        t[i]=s[n-i+1];
        a[s[i]-\'a\'+1].push(i);
    }
    for(int i=1;i<=n;i++)
    {
        c[i]=a[t[i]-\'a\'+1].front();
        a[t[i]-\'a\'+1].pop();
    }
    //   for(int i=1;i<=n;i++)
    //       cout<<c[i]<<" ";
    //  cout<<endl;
    for(int i=1;i<=n;i++)
    {
        add(c[i],1);
        //     cout<<getsum(c[i])<<":";
        res=res+i-getsum(c[i]);
    }
    cout<<res;
    return 0;
}

 

以上是关于Codeforces Round 96 (Rated for Div. 2)E. String Reversal(树状数组求逆序对)的主要内容,如果未能解决你的问题,请参考以下文章

Cow and Snacks(吃点心--图论转换) Codeforces Round #584 - Dasha Code Championship - Elimination Round (rate

Educational Codeforces Round 96 (Rated for Div. 2)C. Numbers on Whiteboard

Codeforces Round 96 (Rated for Div. 2)E. String Reversal(树状数组求逆序对)

Educational Codeforces Round 53 (Rated for Div. 2)

AC日记——Success Rate codeforces 807c

Codeforces 807C - Success Rate