zoukankan      html  css  js  c++  java
  • 「题解」NowCoder7225A 排列

    题目链接:https://ac.nowcoder.com/acm/contest/7225/A

    题目描述

    牛牛拿到了一个长度为N的排列和M个区间,一开始排列是1、2、3......N。

    然后他将这些区间在按顺序在排列上翻转,全部翻转一遍称一次操作。

    现在他要去搞文化了...所以拜托你告诉他经过K次操作后的排列长什么样子。

    输入描述:

    第一行三个整数:N,M,K。

    接下来M行,每行两个整数L和R描述一个区间。

    输出描述:

    输出一行N个数,表示经过K次操作后的排列。

    基本思路

    一开始,我认为对于任何的操作,只要操作两遍就等于没有操作,也就是说所有偶数次的操作都可以被忽略,然而……

    Screenshot_20200905_220229.jpg

    事实证明,我这个方法是不对的,这题也不可能这么简单(实际上我到现在没有找到反例)

    那么换种思路

    记录变化量

    一开始我想到的是,可以先翻转一次,记录这个数组的变化,也就是哪些位置发生了交换。

    之后,就可以直接使用这个变化量来循环操作K次了,时间复杂度为O(NK)

    但是按照这个数据规模,这个时间复杂度一定没有办法AC,怎么办呢?

    倍增思想

    众所周知,倍增是一个特别快的算法,时间复杂度可以降低到对数级,著名的快速幂算法和ST表使用的就是倍增思想。

    稍加思考,很容易发现,求出2此操作后的变化量,可以把操作一次之后的结果在按照这个变化量变化,这样就可以得到操作2次的变化量。

    然后,我们就可以利用操作2次之后的结果 来得出操作两次后 数组的变化量,进而得出操作4次之后的结果。

    如此往复,可以通过递推的方式得到2^n次操作之后的变化量。

    又因为任何一个数都可以拆分成2^a[i]的和(其中a[i]为自然数)。

    比如5次操作可以通过先进行1此操作,再进行4次操作实现,这和快速幂算法是非常接近的。

    于是,我们可以使用记录变化量和倍增的方式达到O(N log K)的时间复杂度。

    代码

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    const int Max=100005;
    
    int main(){
    //	freopen("data.in", "r", stdin);
    	int n, m, k, pre[Max], tmp, l, r;
    	scanf("%d %d %d", &n, &m, &k);
    /*	if(!(k&1)){
    		for(int i=1; i<=n; i++) printf("%d ", i);
    		return 0;
    	}*/
    	for(int i=1; i<=n; i++) pre[i]=i;
    	for(int i=0; i<m; i++){
    		scanf("%d %d", &l, &r);
    		for(int j=l; j<=((l+r)>>1); j++){
    			tmp=pre[j];
    			pre[j]=pre[r-(j-l)];
    			pre[r-(j-l)]=tmp;
    		}
    	}
    	int now[Max], ans[Max], ansbak[Max];
    	for(int i=1; i<=n; i++) now[i]=pre[i];
    	for(int i=1; i<=n; i++) ans[i]=i;
    	while(k){
    		if(k&1){
    			for(int i=1; i<=n; i++){
    				ansbak[i]=ans[i];
    			}
    			for(int i=1; i<=n; i++){
    				ans[i]=ansbak[now[i]];
    			}
    		}
    		for(int i=1; i<=n; i++){
    			now[i]=pre[pre[i]];
    		}
    		for(int i=1; i<=n; i++) pre[i]=now[i];
    		k>>=1;
    	}
    	for(int i=1; i<=n; i++) printf("%d ", ans[i]);
    
    	return 0;
    }
    
    
  • 相关阅读:
    OA并发用户数(转)
    mysql中limit用法[转]
    解决IE浏览器中AJAX只能运行一次的IE缓存问题
    ASP.NET AJAX 1.0 beta 发布了...
    开始我的第一个WPF程序
    前WPF PM 用WPF写的一个XAML即时编辑器 kaxaml
    啊..要死了...
    const 和 static readonly
    DCDC Converter(六)同步整流管
    DCDC Converter(三)效率之计算(2):Discontinuous Mode
  • 原文地址:https://www.cnblogs.com/dong628/p/13620036.html
Copyright © 2011-2022 走看看