zoukankan      html  css  js  c++  java
  • Codeforces 414C Mashmokh and Reverse Operation

    题意:给你2^n个数,每次操作将其分成2^k份,对于每一份内部的数进行翻转,每次操作完后输出操作后的2^n个数的逆序数。

    解法:2^n个数,可以联想到建立一棵二叉树的东西,比如  2,1,4,3就可以建成下面这样

                                                        [2,1,4,3]                        level 2

                                                       /              

                                                  [2,1]              [4,3]                  level 1

                                               /                      /    

                                            [2]         [1]        [4]    [3]              level 0

    然后算某个区间的逆序数的时候[2,1,4,3]实际上就是算[2,1],[4,3]的逆序数再加上[2,1],[4,3]之间的逆序数,思路和归并排序是一样的。

    然后我们看下每次翻转,假如我们分成2^k份,我们会发现,对于level k+1层以上的逆序数是不会改变的,但是level k~level 0的逆序数对会翻转,我们只需要知道level k~level 0各个区间翻转后的逆序数就可以了。 

    所以做法就有点类似于归并求逆序数,对于每个结点,记inv[0]为不翻转时的逆序数,inv[1]为翻转的时候的逆序数,然后我们记sum[k][0]和sum[k][1] 为该层所有结点的inv[0]的和 以及inv[1]的和。 然后每次操作就是将 sum[k~0]的0,1值交换,然后逆序数就是sum[n~0][0]的和。

    #pragma warning(disable:4996)
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #define ll long long
    #define maxn 2000000
    using namespace std;
    
    ll a[maxn];
    int n;
    
    ll sum[25][2];
    
    void build(int dep,int L, int R)
    {
    	if (dep == 0){
    		sum[dep][0] = sum[dep][1] = 0; return;
    	}
    	int M = (L + R) >> 1;
    	build(dep - 1, L, M); build(dep - 1, M + 1, R);
    	for (int i = L; i <= M; i++){
    		sum[dep][1] += a+R+1-upper_bound(a + M + 1, a + R + 1, a[i]);
    		sum[dep][0] += lower_bound(a + M + 1, a + R+1, a[i]) - (a + M + 1);
    	}
    	sort(a + L, a + R + 1);
    };
    
    int main()
    {
    	while (cin >> n)
    	{
    		memset(sum, 0, sizeof(sum));
    		int tot = 1 << n;
    		for (int i = 1; i <= tot; i++){
    			scanf("%I64d", a + i);
    		}
    		build(n, 1, tot);
    		int m, q;
    		cin >> m;
    		for (int i = 0; i < m; i++){
    			scanf("%d", &q);
    			for (int j = q; j >= 0; j--){
    				swap(sum[j][0], sum[j][1]);
    			}
    			ll ans = 0;
    			for (int j = n; j >= 0; j--){
    				ans += (ll)sum[j][0];
    			}
    			printf("%I64d
    ", ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    appium 滑动屏幕
    appium 根据属性名获取属性值 特殊情况 element.get_attribute('name')相当于element.get_attribute('content-desc')或element.get_attribute('text')
    appium 获取元素的内容 获取元素的位置和大小
    appium 点击 输入 清空 ;异常处理 当输入中文 ,没有效果时,需要前置代码里加两行代码
    appium 隐式 查找元素
    appium 过滤出带有‘设’的文本
    appium 批量找元素
    通过id class xpath 找元素
    随笔
    spring 事务传播特性
  • 原文地址:https://www.cnblogs.com/chanme/p/3650544.html
Copyright © 2011-2022 走看看