给逆序对数求原数组

Posted Keep--Silent

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给逆序对数求原数组相关的知识,希望对你有一定的参考价值。

文章目录

给正序对数求原数组

假设 正序对数是 0    1    2    1    2 0\\; 1 \\;2\\; 1\\; 2 01212
解决:

  1. 先管正序对数小的,从小往大放
  2. 正序对数相同时,从右往左放

0    0    0    0    0 0 \\; 0 \\; 0\\; 0 \\; 0 00000
1    0    0    0    0 1\\; 0\\; 0\\; 0 \\; 0 10000
1    3    0    2    0 1\\; 3\\; 0 \\; 2\\; 0 13020
1    3    5    2    4 1\\; 3 \\; 5 \\; 2 \\; 4 13524

例题
这题需要根据残缺的数组,补齐原数组

#include<bits/stdc++.h>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
#define SIZE (1000000+10)
int a[SIZE];
int b[SIZE];
int flag[SIZE];
vector<int>pot[SIZE];
int main() 
    int i,j,n,k,p,x;
    scanf("%d%d",&n,&k);
    for(i=0;i<k;i++)
        scanf("%d%d",&p,&x);
        b[p]=x;
    
    int maxn=0;
    for(i=1;i<=n;i++)
        if(b[i]==0)b[i]=b[i-1]+1;
        else 
            if(b[i]>maxn+1)
                cout<<-1<<endl;
                return 0;
            
        
        maxn=max(maxn,b[i]);
        pot[b[i]].push_back(i);     
    
    int ans=1;
    for(i=1;i<=n;i++)
        for(j=pot[i].size()-1;j>=0;j--)
            a[pot[i][j]]=ans++;
        
    
    //for(i=1;i<=n;i++)printf("%d ",b[i]);cout<<endl;
    for(i=1;i<=n;i++)printf("%d ",a[i]);cout<<endl;
   
    return 0;

给逆序对数求原数组(原数各不相同

排序
本题关键是得到原数组

  1. 放入 0    0    1    2    . . .      x − 1    x    x + 1    . . . n − 2 0\\;0 \\;1 \\;2\\; ...\\;\\;x-1\\; x \\;x+1\\;... n-2 0012...x1xx+1...n2
  2. 多余的数从第二个位置开始加 ,可以得到逆序对数 0    1    2    . . . x    x    x + 1...    n − 2 0\\; 1 \\;2 \\;...x\\; x\\; x+1... \\;n-2 012...xxx+1...n2
  3. 然后再用当前位置扣去数字,可以得到正序对数 0    0    1    1    . . .    1    0    . . .    0    0\\; 0\\; 1 \\;1\\; ... \\;1\\; 0 \\;... \\;0 \\; 0011...10...0
  4. 先放0 ,再放1,从右往左放
#include<bits/stdc++.h>
using namespace std;
const int Size = 1e5 + 10;
#define ll long long
#define debug(x) cout<<#x<<" = "<<x<<" ";
#define debug1(a) debug(a);cout<<endl;
#define debug2(a,b) debug(a);debug1(b);
#define debug3(a,b,c) debug(a);debug2(b,c);
#define debugvec(x,n) cout<<#x<<": ";for(int asd=0;asd<n;asd++)cout<<x[asd]<<" ";cout<<endl;
#define debugvector(x) cout<<#x<<": ";for(int asd=0;asd<x.size();asd++)cout<<x[asd]<<" ";cout<<endl;
#define debugvectorstring(x) cout<<#x<<": ";for (auto& s : x) printf("%s", s.c_str());;cout<<endl;
int n, k = 100;
string s, ans;
vector<int>v;
void ini() 
    int i, t;
    n = 1;
    while (n * (n - 1) / 2 < k) n++;
    v.push_back(0);
    for (i = 0; i < n - 1; i++)v.push_back(i);
    t = k - (n - 2) * (n - 1) / 2;
    //debug3(k, (n - 2) * (n - 1) / 2, t);
    for (i = n - 1; t; t--, i--)v[i]++;
    for (i = 0; i < n; i++)v[i] = i - v[i];
    //debugvec(v, n);

void sovle() 
    int i;
    char ch = 'a';
    s.resize(n);
    for (i = n - 1; i >= 0; i--)if (!v[i]) s[i] = ch++;
    for (i = n - 1; i >= 0; i--)if (v[i]) s[i] = ch++;
    cout << s << endl;

int main() 
    //freopen("C:\\\\Users\\\\31531\\\\Desktop\\\\input.txt", "r", stdin);
    ini();
    sovle();
    return 0;

给逆序对数求原数组(原数可相同

字串排序

k ≤ 26 ( 26 − 1 ) 2 = 325 时 k \\leq \\cfrac26(26-1)2=325时 k226(261)=325

  1. 放入 0    0    1    2    . . .      x − 1    x    x + 1    . . . n − 2 0\\;0 \\;1 \\;2\\; ...\\;\\;x-1\\; x \\;x+1\\;... n-2 0012...x1xx+1...n2
  2. 从倒二位开始 v [ i ] + + v[i]++ v[i]++,每次往前挪两格 i − = 2 i-=2 i=2
  3. 从正二位或者正三位开始 v [ i ] + + v[i]++ v[i]++,每次往后挪两格 i + = 2 i+=2 i+=2
  4. 已经是递增的顺序了,直接从右往左放
#include<bits/stdc++.h>
using namespace std;
const int Size = 3e3 + 10;
#define ll long long
#define debug(x) cout<<#x<<" = "<<x<<" ";
#define debug1(a) debug(a);cout<<endl;
#define debug2(a,b) debug(a);debug1(b);
#define debug3(a,b,c) debug(a);debug2(b,c);
#define debugvec(x,n) cout<<#x<<": ";for(int asd=0;asd<n;asd++)cout<<x[asd]<<" ";cout<<endl;
#define debugvector(x) cout<<#x<<": ";for(int asd=0;asd<x.size();asd++)cout<<x[asd]<<" ";cout<<endl;
#define debugvectorstring(x) cout<<#x<<": ";for (auto& s : x) printf("%s", s.c_str());;cout<<endl;
string s = "";
int n,k=100;
vector<int>v;
void debugs(string s) 
	for (auto ch : s) 
		printf("%3c", ch);
	
	cout << endl;
	int p[2] =  0,0 ;
	for (int i = 0; i < s.size(); i++) 
		int cnt = 0;
		for (int j = i - 1; j >= 0; j--) 
			if (s[j] > s[i]) 
				cnt++;
			
		
		p[1] += cnt;
		printf("%3d", cnt);
	
	cout << endl;
	//debug2(p[0], p[1]);

void ini() 
	int i, t;
	n = 1;
	while (n * (n - 1) / 2 < k) n++;
	t = k - (n - 1) * (n - 2) / 2;
	v.push_back(0);
	for (i = 0; i < n - 1; i++)v.push_back(i);
	//debugvec(v, n);
	for (i = n - 2; i > 0 && t; i-=2, t--)v[i]++;
	//debugvec(v, n);
	for (i = 1 + (n % 2); t; t--, i += 2)v[i]++;
	//debugvec(v, n);

void solve() 
	s.resize(n);
	char ch = 'a';
	s[n - 1] = ch;
	for (int i = n 以上是关于给逆序对数求原数组的主要内容,如果未能解决你的问题,请参考以下文章

给逆序对数求原数组

归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对

归并排序(逆序对数)

算法设计《分治法》归并排序实例分析之逆序对数

POJ-2299 Ultra-QuickSort(用树状数组求逆序对数)

Todo求逆序对数总结