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

摘要:
Input第一行中的正整数n表示字符串的长度。第二行和第三行各有一个长度为n的字符串,并且只包含大写英文字母。输出是表示最小交换数的非负整数。SampleInput3ABCBCASampleOutput2HINABC-˃BAC-˃BCASource感谢oimaster。首先,以最少的次数交换相邻元素等,必须使用树阵列来查找逆序对。然后,上面的示例可以得到序列:12435,然后反转序列以愚弄他人…请参见程序了解详细信息。您可以通过自己推送来理解^w^PS:将int变量分配给char类型也很酷。。。

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("
%s
%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 }

免责声明:文章转载自《Bzoj 2789: [Poi2012]Letters 树状数组,逆序对》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇笔记--随时更新【原创】打造基于Dapper的数据访问层下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

unity_数据结构(常见数据结构及适用场景)

常见的数据结构: 1.Array: 最简单的数据结构 特点:数组存储在连续的内存上。数组的内容都是相同类型。数组可以直接通过下标访问。优点:由于是在连续内存上存储的,所以它的索引速度非常快,访问一个元素的时间是恒定的也就是说与数组的元素数量无关,而且赋值与修改元素也很简单。缺点:由于是连续存储,所以在两个元素之间插入新的元素就变得不方便。声明一个新的数组时...

深入理解HashMap第一篇

HashMap 1.描述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现。设计目标是尽量实现哈希表O(1)级别的增删改查效果,与HashTable主要区别为不支持同步和允许null作为key和value。 各项默认值 初始容量(capacity):16(1<<4),即2^4。 最大容量:(1<<30),即...

ArrayList的使用方法

1、什么是ArrayListArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小 2、如何使用ArrayList最简单的例子:ArrayListList=newArrayList();for(int...

VBS数组函数学习实例分析

Array 函数 返回包含数组的Variant。 Array(arglist) 参数:arglist是赋给包含在Variant中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则将会创建零长度的数组。 说明:用于引用数组元素的表示符,由跟随有括号的变量名组成,括号中包含指示所需元素的索引号。 在下面的示例中,第一条语句创建名为 A 的...

C#6.0语言规范(十二) 数组

数组是一种数据结构,包含许多通过计算索引访问的变量。包含在数组中的变量(也称为数组的元素)都是相同的类型,这种类型称为数组的元素类型。 数组具有确定与每个数组元素相关联的索引数的等级。数组的等级也称为数组的维度。秩为1的数组称为一维数组。秩大于1的数组称为多维数组。特定大小的多维阵列通常被称为二维阵列,三维阵列等。 数组的每个维度具有相关联的长度,该长度是...

gin 框架目录

一个 Gin 项目结构示例 IllIIlIlIII关注 0.4632019.07.18 02:21:02字数 144阅读 6,104 ├── gin │ ├── Router │ └── router.go │ ├── Middlewares │ └── corsMiddleware.go │...