zoukankan      html  css  js  c++  java
  • Luogu P3149 排序(树状数组、前缀和)

    P3149

    思路:

    稍微模拟一下就能发现,每一次的操作其实就是将“第1~第k个位置上的值”的逆序对的贡献清零。

    那么我们先对数据离散化后用树状数组求出每个位置上的值能贡献的逆序对,并使用前缀和加速逆序对的区间求值。

    值得注意的一点是按照从大到小的顺序去修改树状数组就可以计算出每个位置上的值贡献的逆序对。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL N = 300010;
    
    struct Node {
    	LL val, pos; //pos为第几个出现
    	LL opt; //该点贡献的逆序对
    	bool operator<(const Node& t) const {
    		if (val == t.val) return pos < t.pos;
    		else return val < t.val;
    	}
    } a[N];
    LL tr[N], r[N], ta[N], atot;
    LL n, m, ans, trans[N]/*第i个位置上的数是几*/;
    LL sum[N];
    
    void update(LL x, LL k) {
    	for (; x <= n; x += x & -x)
    		tr[x] += k;
    }
    
    LL query(LL x) {
    	LL res = 0;
    	for (; x; x -= x & -x) 
    		res += tr[x];
    	return res;
    }
    
    int main() {
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	cin >> n >> m;
    	for (LL i = 1; i <= n; i++) {
    		cin >> a[i].val;
    		a[i].pos = i;
    		ta[++atot] = a[i].val;
    	}
    
    	sort(ta + 1, ta + 1 + atot);
    	atot = unique(ta + 1, ta + 1 + atot) - ta - 1; //atot为离散后的表长
    
    	for (LL i = n; i >= 1; i--) { //倒着求就可以算出每个点所产生的逆序对的数量
    		a[i].val = lower_bound(ta + 1, ta + 1 + atot, a[i].val) - ta; //离散化,即原来的数->原来的数是第几小的
    		a[i].opt = query(a[i].val - 1); //在他之后还比他小的 即 a[i].val贡献的逆序对数量
    		ans += a[i].opt;
    		update(a[i].val, 1);
    	}
    
    	sort(a + 1, a + 1 + n); //求排序后的前缀和。因为要减掉的是小于等于第k个位置的值的逆序对总贡献
    	for (LL i = 1; i <= n; i++) {
    		sum[i] = sum[i - 1] + a[i].opt;
    		trans[a[i].pos] = i; //[原来的数的位置]->在排序后的位置
    	}
    
    	cout << ans << endl;
    	LL maxval = 0, nowopt = 0;
    	for (LL i = 1; i <= m; i++) {
    		LL k; cin >> k;
    		if (a[trans[k]].val >= maxval) {
    			nowopt = sum[n] - sum[trans[k]];
    			cout << nowopt << endl;
    			maxval = a[trans[k]].val;
    		} else { //这一段已经排过序,不再贡献逆序对
    			cout << nowopt << endl;
    		}
    	}
    	return 0;
    }
    
    /*
    4 2
    1 4 2 3
    4
    3
    
    5 2
    2 6 3 5 4
    3
    4
    
    */
    
  • 相关阅读:
    (转)CSS3之pointer-events(屏蔽鼠标事件)属性说明
    Linux下source命令详解
    控制台操作mysql常用命令
    解决beego中同时开启http和https时,https端口占用问题
    有关亚马逊云的使用链接收集
    favicon.ico--网站标题小图片二三事
    网络博客
    Gitbook 命令行工具
    Markdown 轻量级标记语言
    SVN 集中式版本控制系统
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14331367.html
Copyright © 2011-2022 走看看