Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 278  Solved: 185
[Submit][Status][Discuss]

Description

给出两个长度相同且由大写英文字母组成的字符串A、B,保证A和B中每种字母出现的次数相同。

现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B。

 

Input

 

 

第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度。

第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母。

 

 

Output

一个非负整数,表示最少的交换次数。

Sample Input

3
ABC
BCA

Sample Output

2

HINT

 

 


 

ABC -> BAC -> BCA

 

 

Source

鸣谢 oimaster

 

题解:

树状数组+逆序对

口胡 :Bzoj好像挂了QAQ,好伤心555555

好了,开始说正题。

首先,最少次数交换相邻的元素之类的肯定用树状数组求逆序对。然后考虑贪心。

这道题的贪心思路很好想,就是把B数列每个数把其在A数列中最近的数移过来。

例如:

A数列 : ABACA

B数列 : ABCAA

对于B数列中每个数,我们去找在A数列中应该出现的位置,若字母相同就往后找,直到找到第一个没有在A数列中选过的位置。

则上述例子可以得到数列:1 2 4 3 5

然后逆序对胡搞。。。

具体看程序,自己手推一下就懂了 ^w^

PS:把int变量定到char类型中也是爽。。。QAQ

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 #define LL long long
 9 #define MAXN 1000010
10 struct node
11 {
12     int v,w;
13 }a[MAXN],b[MAXN];
14 /*struct NODE
15 {
16     int v,w;
17 }b[MAXN];*/
18 int n;
19 int BIT[MAXN],c[MAXN];
20 char A[MAXN],B[MAXN];
21 bool cmp(node aa,node bb)
22 {
23     if(aa.v==bb.v)return aa.w<bb.w;
24     return aa.v<bb.v;
25 }
26 /*bool cmp1(NODE aa,NODE bb)
27 {
28     if(aa.v==bb.v)return aa.w<bb.w;
29     return aa.v<bb.v;
30 }*/
31 int Lowbit(int o){return o&(-o);}
32 void Update(int o,int o1)
33 {
34     while(o<=n)
35     {
36         BIT[o]+=o1;
37         o+=Lowbit(o);
38     }
39 }
40 int Sum(int o)
41 {
42     int sum=0;
43     while(o>0)
44     {
45         sum+=BIT[o];
46         o-=Lowbit(o);
47     }
48     return sum;
49 }
50 int main()
51 {
52     int i;
53     LL ans=0;
54     scanf("%d",&n);
55     scanf("\n%s\n%s",A+1,B+1);
56     for(i=1;i<=n;i++)
57     {
58         a[i].v=A[i]-'A'+1;b[i].v=B[i]-'A'+1;
59         a[i].w=b[i].w=i;
60     }
61     sort(a+1,a+n+1,cmp);
62     sort(b+1,b+n+1,cmp);
63     for(i=1;i<=n;i++)c[a[i].w]=b[i].w;
64     memset(BIT,0,sizeof(BIT));ans=0;
65     for(i=n;i>=1;i--)
66     {
67         ans+=Sum(c[i]-1);
68         Update(c[i],1);
69     }
70     printf("%lld",ans);
71     fclose(stdin);
72     fclose(stdout);
73     return 0;
74 }

 

posted @ 2016-03-30 22:56  微弱的世界  阅读(219)  评论(0编辑  收藏  举报