zoukankan      html  css  js  c++  java
  • 【bzoj2789】[Poi2012]Letters 树状数组求逆序对

    题目描述

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

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

    输入

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

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

    输出

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

    样例输入

    3
    ABC
    BCA

    样例输出

    2


    题解

    树状数组求逆序对

    一个结论:将序列A通过交换相邻元素变换为序列B,需要的最小次数为A中元素在B中的位置所组成的序列的逆序对数。

    当出现重复元素时,由于互不影响,所以让它们按照递增的顺序出现,不产生逆序对就好了。

    然后用树状数组统计一下逆序对数即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 1000010
    using namespace std;
    char A[N] , B[N];
    int n , head[26] , next[N] , f[N];
    void add(int x)
    {
    	int i;
    	for(i = x ; i <= n ; i += i & -i) f[i] ++ ;
    }
    int query(int x)
    {
    	int i , ans = 0;
    	for(i = x ; i ; i -= i & -i) ans += f[i];
    	return ans;
    }
    int main()
    {
    	int i , t;
    	long long ans = 0;
    	scanf("%d%s%s" , &n , A + 1 , B + 1);
    	for(i = 1 ; i <= n ; i ++ ) next[i] = head[A[i] - 'A'] , head[A[i] - 'A'] = i;
    	for(i = n ; i >= 1 ; i -- ) t = head[B[i] - 'A'] , head[B[i] - 'A'] = next[t] , ans += query(t) , add(t);
    	printf("%lld
    " , ans);
    	return 0;
    }
    

     

  • 相关阅读:
    openvswitch 监听端口变化
    Python set() 函数
    openstack-neutron-OVS agent分析
    openvswitch ovs-appctl 使用
    python setup.py install 报错【Project namexxx was given, but was not able to be found.】
    openstack nova 创建虚机流程
    Linux kernel 模块 hello 测试
    openvswitch 流表操作
    软件测试开发之第一篇(测试文档)
    Java工具之Myeclipse程序调试
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7434593.html
Copyright © 2011-2022 走看看