题目要求可转化为查询一个区间内有多少数比val大(或者小)。

区间用线段树分解(logN),每个区间维护一rank树。

rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离散。

首先进行分治,分治的同时归并排序完成离散并计算保存出每个元素和其他元素构成的逆序对iv[i]。(据说这叫归并树

初始值将所有iv求和,一个对被算了两次所以除以二。

每次删除元素val就减去val对应的逆序对。

减去iv[val],但是多减去了和之前删掉元素构成的逆序对(这些逆序对已经算过一次)。

所以把删掉的元素加到线段树里面。

减去当前iv[val]之后,查询并加上当前元素val和之前位置以及之后位置构成逆序对。

复杂度

O(nlogn)预处理,O(m*logn*logn)回答

#include<bits/stdc++.h>
using namespace std; const int maxn = 2e5+, LogN = ; typedef long long ll;
ll invPair;
int a[maxn],p[maxn];
int iv[maxn];
int n; int s[maxn<<];
int C[LogN][maxn];
int Set[LogN][maxn]; #define para int o = 1, int l = 1,int r = n,int dep = 0
#define lo (o<<1)
#define ro (o<<1|1)
#define TEMP int mid = (l+r)>>1, lc = lo, rc = ro;
#define lsn lc, l, mid, dep+1
#define rsn rc, mid+1, r, dep+1 #define lb(x) ((x)&-(x))
int sum(int C[],int x)
{
int re = ;
while(x>){
re += C[x];
x -= lb(x);
}
return re;
} void add(int C[],int x,int d,int r)
{
while(x<=r){
C[x] += d;
x += lb(x);
}
} int qpos;
int ql,qr,val;
void queryPrefix(para)
{
if(<=l&&r<=qr){
int pos = upper_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//等于等于val的最大元素的编号
invPair += s[o] - sum(C[dep]+l-,pos);//得到大于val的元素个数
}else {
TEMP
queryPrefix(lsn);
if(qr>mid) queryPrefix(rsn);
}
} void querySuffix(para)
{
if(ql<=l&&r<=n){
int pos = lower_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//严格小于val的元素的编号
invPair += sum(C[dep]+l-,pos);
}else {
TEMP
if(ql<=mid) querySuffix(lsn);
querySuffix(rsn);
}
} void modify(para)
{
s[o]++;
if(l == r){
C[dep][l] = ;
}else{
TEMP
if(qpos<=mid) modify(lsn);
else modify(rsn);
int pos = upper_bound(Set[dep]+l,Set[dep]+r+,val)-Set[dep]-l;//val在set里,从1开始编号
add(C[dep]+l-,pos,,r-l+);//l-1是0号位,容纳r-l+1个元素
}
} //为保证BIT之间互不影响,merge_sort离散,同时计算逆序对
void discretize(para)
{
s[o] = ;
memset(C[dep]+l,,sizeof(int)*(r-l+));
if(l == r) {
Set[dep][l] = a[l];
return;
}else {
TEMP;
discretize(lsn);
discretize(rsn);
int p = l, q = mid+, k = l;
while(p<=mid || q<=r){
if(q > r|| (p <= mid && Set[dep+][p] <= Set[dep+][q]) ){
iv[Set[dep+][p]] += k-p;//和后面的数构成逆序对
Set[dep][k++] = Set[dep+][p++];
}else {
iv[Set[dep+][q]] += mid-p+;//和前面的数构成逆序对
Set[dep][k++] = Set[dep+][q++];
}
}
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int m;
while(~scanf("%d%d",&n,&m)){
memset(iv+,,sizeof(int)*n);
for(int i = ; i <= n; i++){
scanf("%d",a+i);
p[a[i]] = i;
}
invPair = ;
discretize();
for(int i = ; i <= n; i++){
invPair += iv[i];
}
invPair >>= ;
while(m--){
scanf("%d",&val);
printf("%lld\n",invPair);
invPair -= iv[val];
qr = p[val]-;
ql = p[val]+;
if(qr>=) queryPrefix();
if(ql<=n) querySuffix();
qpos = p[val];
modify();
}
}
return ;
}

UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)的更多相关文章

  1. UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)

    [题目链接] UVA11990 [题目大意] 给出一个数列,每次删去一个数,求一个数删去之前整个数列的逆序对数. [题解] 一开始可以用树状数组统计出现的逆序对数量 对于每个删去的数,我们可以用线段树 ...

  2. UVA 11990 ``Dynamic'' Inversion 动态逆序对

    ``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...

  3. uva 12003 Array Transformer (线段树套平衡树)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  4. BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)

    题目链接or Here 题意:n个数,有两个操作:1.修改某个数为v:2.询问一段区间第k小的数 如果没有修改,则可以用线段树,每个节点P[a,b]存储大小为b-a+1的数组,代表其中的数 同时,这个 ...

  5. UVA 11990 ``Dynamic'' Inversion (序列分治)

    26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...

  6. UVA 11990 `Dynamic'' Inversion CDQ分治, 归并排序, 树状数组, 尺取法, 三偏序统计 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  7. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  8. BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

    之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...

  9. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

随机推荐

  1. [CentOS7] firewalld重启失败 Failed to start firewalld - dynamic firewall daemon.

    错误信息: Failed to start firewalld - dynamic firewall daemon. 如图: 解决方法: 也就是kernel不支持现在的firewall防火墙的某些模块 ...

  2. 在Linux系统下远程连接oracle的防火墙设置

    在Linux系统要远程连接Oracle的防火墙设置方法: 打开5801至5810 端口用于vnc iptables -I INPUT -p tcp --dport 5801:5810 -j ACCEP ...

  3. Tomcat&Servlet

    Tomcat&Servlet 一.web开发相关的概念 1. 软件架构 1.1 C/S架构 C:Client客户端, S:Server服务器 比如:QQ.微信.大型网游 优点: 显示效果炫 安 ...

  4. 安装php过程中的错误和解决方式 configure: error: jpeglib.h not found

    centos6.5 32位系统: checking for the location of libpng... yeschecking for the location of libXpm... no ...

  5. redis使用方法

    redis缓存服务器笔记 redis是一个高性能的key-value存储系统,能够作为缓存框架和队列 但是由于他是一个内存内存系统,这些数据还是要存储到数据库中的 作为缓存框架: create/upd ...

  6. CF C. Maximal Intersection(贪心 || STL)

    题意 给你N个线段(一条直线上),问删去一个之后,最长公共长度 : 分析:首先我们得先知道n条线段公共的线段一定是(LMAX,RMIN) ,那我们可以先排序,然后枚举删除边: #include< ...

  7. 插入po得到主键,插入sql得到主键

    import com.yd.common.data.CIPPageInfo; import com.yd.common.data.CIPReqCondition; import com.yd.comm ...

  8. Scrapy(爬虫应用框架)安装配置

    运行平台:Windows Python版本:Python3.x 一.Scarpy 简介 Scrapy是一个为了爬取网站数据提取结构性数据而编写的应用框架,可以应用于数据挖掘,信息处理或存储历史数据等一 ...

  9. 转 rman-08120 以及查询隐含参数

    rman-08120 We need RMAN to automatically purge archivelogs from the FRA once they are applied to the ...

  10. Appium + Python自动化3 - 输入中文

    在做app自动化过程中会踩很多坑,咱们都是用中文的app,所以首先要解决中文输入的问题!本篇通过屏蔽软键盘,绕过手机的软键盘方法,解决中文输入问题. 一.定位搜索 1.打开淘宝点击搜索按钮,进入搜索页 ...