• T107073 归并排序


    https://www.luogu.com.cn/problem/T107073

    众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关系。

    小葱同学在听小学数学老师讲了如何用归并排序求逆序对之后,就觉得这东西还不如跑一个线段树来做。但是这天,小葱的语文老师告诉小葱这么一个问题:我们原来是给定NN个数,然后通过归并排序在合并左右区间的时候,求出了左右两个区间之间形成了多少个逆序对。那如果我们现在换一个问题,现在我们是告 诉了你每次合并左右区间的时候的产生的逆序对数量, 你能不能把原有的序列复现出来呢?关于更多细节,请参考数据规模与约定的部分。

    别参考了知道这个意思就行

    (=============================================)
    因为我们只需要构造一组解
    所以说 在归并排序合并操作的时候
    分左边 右边两个区间
    假设这个区间合并时应该要(v)个逆序对
    不妨右边前(v/mid)个全都为最小,这样右边前(v/mid)个每个都贡献(mid)个逆序对
    然后让(v/mid + 1)这个位置贡献(v%mid)个,
    剩下的从(v/mid + 2)(r)都贡献0
    这样对每个合并操作都满足了(v)贡献

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 50;
    int n;
    int z[N], y[N];
    void merge_sort(int l, int r) {
    	if(l == r) return ;
    	int mid = (l + r) >> 1;
    	merge_sort(l, mid), merge_sort(mid + 1, r);
    	int v; scanf("%d", &v);
    	int p = l, p1 = l, p2 = mid + 1;
    	while(v >= mid - p1 + 1) {
    		y[p++] = z[p2++];
    		v -= mid - p1 + 1;
    	}
    	for(int i = p1; i <= mid - v; i++) y[p++] = z[p1++];
    	if(p2 <= r) y[p++] = z[p2++];
    	while(p1 <= mid) y[p++] = z[p1++];
    	while(p2 <= r) y[p++] = z[p2++];
    	for(int i = l; i <= r; i++) z[i] = y[i];
    }
    int main() {
    	cin>>n;
    	for(int i = 1; i <= n ;i++) z[i] = i;
    	merge_sort(1, n);
    	for(int i = 1;i <= n; i++) y[z[i]] = i;
    	for(int i= 1; i <= n ; i ++) printf("%d ", y[i]);
    }
    
  • 相关阅读:
    MySQL客户端管理
    Windows10安装Pytorch环境要点
    使用ssh加密github通信
    JVM 对象状态判断01
    并发之AbstractQueuedLongSynchronize----AQS
    关于CountDownLatch控制线程的执行顺序
    关于线程执行顺序的问题
    并发之Striped64(l累加器)
    并发之线程以及线程的中断状态
    1 JPA入门----项目搭建以及CRUD
  • 原文地址:https://www.cnblogs.com/skkyk/p/14066624.html
Copyright © 2020-2023  润新知