• [BZOJ3295][Cqoi2011]动态逆序对


    [BZOJ3295][Cqoi2011]动态逆序对

    试题描述

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    输入

    输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。

    输出

    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    输入示例

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    输出示例

    5
    2
    2
    1

    数据规模及约定

    N<=100000 M<=50000

    题解

    树状数组套主席树不解释。内存卡卡常。。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 100010
    #define maxnode 10100000
    #define LL long long
    
    int ToT, sumv[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p, int v) {
    	sumv[y = ++ToT] = sumv[x] + v;
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p, v);
    	else update(rc[y], rc[x], mid+1, r, p, v);
    	return ;
    }
    int query(int o, int l, int r, int ql, int qr) {
    	if(!o) return 0;
    	if(ql <= l && r <= qr) return sumv[o];
    	int mid = l + r >> 1, ans = 0;
    	if(ql <= mid) ans += query(lc[o], l, mid, ql, qr);
    	if(qr > mid) ans += query(rc[o], mid+1, r, ql, qr);
    	return ans;
    }
    
    int n, A[maxn], pos[maxn], Rt[maxn], rt[maxn];
    void modify(int x, int v) {
    	for(; x <= n; x += x & -x) update(Rt[x], Rt[x], 1, n, v, -1);
    	return ;
    }
    int ask(int x, int vl, int vr) {
    	int ans = query(rt[x], 1, n, vl, vr);
    	for(; x; x -= x & -x) ans += query(Rt[x], 1, n, vl, vr);
    	return ans;
    }
    
    int main() {
    //	freopen("data.in", "r", stdin);
    //	freopen("data.out", "w", stdout);
    	n = read(); int q = read();
    	LL ans = 0;
    	for(int i = 1; i <= n; i++) {
    		A[i] = read(); pos[A[i]] = i;
    		update(rt[i], rt[i-1], 1, n, A[i], 1);
    		ans += query(rt[i-1], 1, n, A[i] + 1, n);
    	}
    	while(q--) {
    		printf("%lld
    ", ans);
    		int p = pos[read()];
    		modify(p, A[p]);
    		ans -= ask(p - 1, A[p] + 1, n) + ask(n, 1, A[p] - 1) - ask(p, 1, A[p] - 1);
    //		printf("ToT: %d
    ", ToT);
    	}
    	
    	return 0;
    }
    

    双倍经验:BZOJ2141,改改操作。。。

  • 相关阅读:
    C#手写日志(txt格式)
    dedecms:解析Robots.txt 协议标准
    dedecms列表页有图调用缩略图无图留空的方法
    简单的随机数实现
    单页面定时跳转的办法小结
    css3通过scale()实现放大功能、通过rotate()实现旋转功能
    rem自适应布局小结001
    Java的BIO、NIO、AIO
    Java实现静态代理、动态代理
    博弈论基础
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6363563.html
Copyright © 2020-2023  润新知