给逆序对数求原数组

给正序对数求原数组

假设 正序对数是 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 \cfrac{26(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 - 2; i >= 0; i--) {
		if (v[i] == v[i + 1])s[i] = ch;
		else s[i] = ++ch;
	}
}
int flag = 26 * 25 / 2;
int main() {
	//freopen("C:\\Users\\31531\\Desktop\\input.txt", "r", stdin);
	//debugs("bbaa");
	//debugs("jihgfeeddccbbaa");
	cin >> k;
	if (k > flag)while (1);
	ini();
	solve();
	cout << s;
	return 0;
}

k > 26 ( 26 − 1 ) 2 时 k>\cfrac{26(26-1)}{2}时 k>226(261)待续

  • 2237
  • gzyyxxwwvvuuttssrrqqppoonnmmllkkkjjjiiihhhgggffffeeeeddddccccbbbbaaaa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值