首页 > 其他分享 >CF EDU 96 E - String Reversal

CF EDU 96 E - String Reversal

时间:2022-08-14 19:22:29浏览次数:92  
标签:字符 ch String idx int CF 逆序 include 96

贪心、逆序对

E - String Reversal

题意

给一个长度为 n 的字符串 s,(n <= 2e5), 把 s 反转后的字符串记为 s', 每次只可以交换相邻两个字符,求把 s 变为 s' 的最小次数

思路

  1. 可以从左到右枚举 s,对于当前位置 i,字符 a 要变成 字符 b,则较靠前的 a 要去给较靠前的 b 匹配(没有必要把原串的第 1 个 ch 作为目标串的最后 1 个 ch,而是也作为第 1 个),这样移动次数一定是最优的

    具体可以用 二维vector 存下每个字符的位置,G[ch] 为字符 ch 的所有位置,且位置按升序排列

    对于每个 G[ch] 再 reverse 一下,位置按逆序排列

    从 1 到 n 枚举位置 i 要变成的字符,其实就是从 n 到 1 枚举原字符串,设当前枚举的字符是 ch,就是找 G[ch].back(), 再弹出即可

  2. 这样就找到了每个位置 i 与之匹配的位置

    在这个数组中求逆序对就是答案(类似冒泡排序最小次数就是逆序对个数)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;
#define endl "\n"

typedef long long ll;
typedef pair<int, int> PII;

const int N = 2e5 + 10, M = 27;
int n;
int a[N], tr[N];
vector<vector<int> > G(M);

int lowbit(int x)
{
	return x & -x;
}

int sum(int idx)
{
	int ans = 0;
	for (int i = idx; i; i -= lowbit(i))
		ans += tr[i];
	return ans;
}

void add(int idx, int k)
{
	for (int i = idx; i <= n; i += lowbit(i))
		tr[i] += k;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		char x;
		cin >> x;
		a[i] = x - 'a' + 1;
		G[a[i]].push_back(i);
	}
	for (int i = 1; i < M; i++)
		reverse(G[i].begin(), G[i].end());

	ll ans = 0;
	for (int i = n; i >= 1; i--)
	{
		int v = G[a[i]].back();
		// cout << v << endl;
		G[a[i]].pop_back();
		ans += sum(n) - sum(v-1);
		add(v, 1);
	}
	cout << ans << endl;
    return 0;
}

标签:字符,ch,String,idx,int,CF,逆序,include,96
From: https://www.cnblogs.com/hzy717zsy/p/16586092.html

相关文章

  • NC16496 [NOIP2014]飞扬的小鸟
    题目链接题目题目描述为了简化问题,我们对游戏规则进行了简化和改编:\1.游戏界面是一个长为n,高为m的二维平面,其中有k个管道(忽略管道的宽度)。\2.小鸟始终在游戏界......
  • CF EDU 97 E - Make It Increasing
    LISE-MakeItIncreasing题意给定数组$a$,(n<=5e5),有一个集合b,b里面存的是a数组的某些下标,这些位置的a的值不能改变其余位置可花1代价变为任意一个整......
  • CF986C AND Graph(图论+二进制连边)
    CF986CANDGraph\(\color{yellow}{\bigstar\texttt{Hint}}\):和每个点连接的点是这个数取反后的子集,考虑将这个点和它的反连边,那么所有对应的数的子集都是同一个连通块内......
  • CF559E Gerald and Path(DP)
    CF559EGeraldandPath设\(dp(i,p)\)表示完成前\(i\)条线段的覆盖,最右端位于\(p\)点的最大收益。转移?向下一条线段转移时加上他们中间的距离?发现这样没有办法统计......
  • CF856D Masha and Cactus(树上 DP+抵消贡献技巧)
    CF856DMashaandCactus我们先捞出一个根节点,那么一次旋变就是对路径上点的覆盖。设\(dp_{i,0}\)表示\(i\)没有选择时子树内最大收益,\(dp_{i,1}\)表示\(i\)选择......
  • CF464E The Classic Problem(线段树 最短路)
    CF464ETheClassicProblem\(\bigstar\texttt{Hint}\):发现没有什么好的突破口?为什么不想想怎样才能实现题目中\(2^x\)的加减法呢?可见每次加减法,我们要做的是将添加的......
  • CF512D Fox And Travelling(DP 计数)
    CF512DFoxAndTravelling给定一张\(n\)个点\(m\)条边的无向图,每次选择一个叶子结点并将它和连接它的边删除。对于每个\(k\in[0,n]\),问有序选择\(k\)个点的方案......
  • CF EDU 131 D - Permutation Restoration
    贪心、扫描线思想D-PermutationRestoration题意有\(1-n\)的一个排列\(a_i\),给定\(b_i\),满足\(b_i=\lfloor\fraci{a_i}\rfloor\),求\(a_i\)(n<=5e5)......
  • CF722E Research Rover
    ResearchRoverCF722E(Luogu)题面翻译有一个n*m的网格图,图中有k个特殊点。初始时你有一个权值s,并且只能向下或向右走,每经过一个特殊点会使得你的权值/2(向上取整)。......
  • String.valueOf 出来的值为null,null为一个字符串
    id为null时候,这个null为一个字符串,当用  StringUtils.isBlank判断时候会出现false  改用 ......