zoukankan      html  css  js  c++  java
  • PAT顶级 1027 Larry and Inversions (35分)(树状数组)

    题目链接:

    1027 Larry and Inversions (35分)

    思路:

    首先计算出原数组逆序数的对数;
    然后依次考虑翻转的情况,我们注意到翻转是有规律的:
    假设我们已经计算得出了从i翻转到j的逆序数对数,则计算i翻转到j+1的逆序数对数,我们只需知道i到j的数中比第j+1个数小的数的个数,我们记为sm,则比j+1个数大的数的数量自然就是j-i-sm,记为gt,那此次翻转我们新获得的逆序数有sm个,损失的逆序数有gt个;
    以上方法需要熟练使用树状数组;

    代码:

    #include<bits/stdc++.h>
    #define lowbit(x) (x&-x)
    
    using namespace std;
    
    const int maxn = 1234;
    int n, a[maxn], sum;
    void init_(){
    	vector<int> bit(n + 1);
    	for(int i = n - 1; i >= 0; i--){
    		int x = a[i], y = a[i];
    		while(x) sum += bit[x], x -= lowbit(x);
    		while(y <= n) ++bit[y], y += lowbit(y);
    	}
    }
    void solve(){
    	for(int i = 0; i < n; i++){
    		int ans = 0;
    		vector<int> bit(n + 1);
    		for(int j = i; j < n; j++){
    			int x = a[j], y = a[j], sm = 0, gt = 0;
    			while(x) sm += bit[x], x -= lowbit(x);
    			while(y <= n) ++bit[y], y += lowbit(y);
    			gt = j - i - sm;
    			ans = ans + sm - gt;
    			if(i || j) putchar(' ');
    			printf("%d", sum + ans);
    		}
    	}
    }
    int main(){
    //	freopen("Sakura.txt", "r", stdin);
    	scanf("%d", &n);
    	for(int i = 0; i < n; i++) scanf("%d", a + i);
    	init_();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    WCF使用net.tcp寄宿到IIS中
    (转)Dubbo 简单Dome搭建
    Linux压缩解压
    Linux关闭开启防火墙命令
    简单登录(jsp+servlet)
    UVa 10285 Longest Run on a Snowboard [DP]
    UVa 1218 Perfect Service [DFS+DP]
    第三届ACM山东省赛 Pick apples [贪心+动规]
    ZOJ 3326
    HDU 1029
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308700.html
Copyright © 2011-2022 走看看