zoukankan      html  css  js  c++  java
  • [HAOI2009] 求回文串

    对于任意输入的字符串,不断将第 (i) 个字符和第 (i+1) 个字符交换,使得该串最终变为回文串。求最少交换次数。(n leq 10^6)

    Solution

    直观的贪心想法:从左向右遍历每个元素,找到序列最右的与它相同的元素,将这两个元素放到目标序列最左、右端然后从原序列中删去,记录下右元素移动的距离就是答案

    然而暴力模拟的复杂度为 (O(n^2)),考虑将每种字符的所有出现位置插入一个 vector 中,同时用一个标记数组来维护每个元素是否已经被删去

    当我们从左侧找元素的时候,如果遇到了一个没有被标记的元素,就意味着我们找到了一个元素

    然后我们通过这个字符的 vector 找到最右侧的相同字符,定位到它的位置,如果这个元素在标记数组中没有被标记,则算找到,否则从 vector 中弹出这个元素并继续找

    找到以后计算贡献,并且将这个右侧元素从 vector 中抹掉,左、右两个元素同时在 vector 中标记

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int ar[N]; // index: 1 ~ N
    int lowbit(int t) { return t & (-t); }
    void add(int i, int v) {
    	for (; i < N; ar[i] += v, i += lowbit(i));
    }
    int sum(int i) {
    	int s = 0;
    	for (; i > 0; s += ar[i], i -= lowbit(i));
    	return s;
    }
    
    char str[N];
    vector <int> v[26];
    
    int n,ans[N],u[N],tot;
    
    signed main() {
        cin>>str+1;
        n=strlen(str+1);
        for(int i=1;i<=n;i++) v[str[i]-'A'].push_back(i);
        int p1=1, p2=n;
        for(int i=1;i<=n;i++) {
            if(u[i]) continue;
            if(p1>=p2) break;
            while(v[str[i]-'A'].size() && u[v[str[i]-'A'].back()])
                v[str[i]-'A'].pop_back();
            if(v[str[i]-'A'].size()==0) {
                cout<<-1;
                return 0;
            }
            int q=v[str[i]-'A'].back();
            if(q==i) continue;
            u[q]=1;
            v[str[i]-'A'].pop_back();
            u[i]=1;
            tot+=abs(p2-q);
            ans[p1++]=i;
            ans[p2--]=q;
        }
        if(p1==p2) {
            int t=0;
            for(int i=1;i<=n;i++) if(u[i]==0) t=i;
            ans[p1]=t;
            tot+=abs(t-p1);
        }
        tot=0;
        for(int i=1;i<=n;i++) {
            tot+=i-1-sum(ans[i]);
            add(ans[i],1);
        }
        cout<<tot;
    }
    
    
  • 相关阅读:
    java学习(十六):对象的自定义比较,Comparator和Comparable
    Java学习(十五):hashCode的作用
    MySQL存储过程入门教程
    MySQL,SQLServer,Oracle数据库常用字段类型
    Java学习(十四):JDBC方式连接数据库举例
    JavaScript对时间的操作方法
    Java学习(十二):Java中的常用时间操作
    Java学习(十一):Java锁Synchronized,对象锁和类锁举例
    Python基础学习9 类
    Python基础学习8 函数
  • 原文地址:https://www.cnblogs.com/mollnn/p/12435061.html
Copyright © 2011-2022 走看看