``Dynamic'' Inversion

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3141

Description

You are given a permutation f1,2,3,. . . ,ng. Remove m of them one by one, and output the number of
inversion pairs before each removal. The number of inversion pairs of an array A is the number of
ordered pairs (i; j) such that i < j and A[i] > A[j].

Input

The input contains several test cases. The rst line of each case contains two integers n and m
(1 n 200;000, 1 m 100;000). After that, n lines follow, representing the initial permutation.
Then m lines follow, representing the removed integers, in the order of the removals. No integer will
be removed twice. The input is terminated by end-of-le (EOF).

Output

For each removal, output the number of inversion pairs before it.
Explanation: (1,5,3,4,2)->(1,3,4,2)->(3,4,2)->(3,2)->(3)

Sample Input

5 4
1
5
3
4
2
5
1
4
2

Sample Output

5
2
2
1

HINT

题意

给你n个数,然后有m次操作,每次操作可以删除一个数

然后问你每次删除之前,还有多少个逆序对

题解:

对于每个数关于逆序对的贡献,就是

这个数前面有多少个数比他大,后面有多少个数比他小

这就是贡献~

然后我们就树状数组套treap来维护这些信息就好了

线段树会TLE。。。

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std;
inline long long read()
{
long long x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
#define maxn 12200005
long long tmp = ;
int a[maxn];
int pos[maxn];
int n,m;
////////////////treap
struct Treap
{
int root[maxn],sz,s[maxn],ls[maxn],rs[maxn],v[maxn],w[maxn],rnd[maxn];
void init()
{
memset(root,,sizeof(root));
sz=;
}
void Updata(int k)
{
s[k]=s[ls[k]]+s[rs[k]]+w[k];
}
void Rturn(int &k)
{
int t;
t=ls[k],ls[k]=rs[t],rs[t]=k,s[t]=s[k];
Updata(k);k=t;
}
void Lturn(int &k)
{
int t;
t=rs[k],rs[k]=ls[t],ls[t]=k,s[t]=s[k];
Updata(k);k=t;
}
void Insert(int &k,int num)
{
if(!k)
{
k=++sz;s[k]=w[k]=;ls[k]=rs[k]=;rnd[k]=rand();
v[k]=num;return;
}
s[k]++;
if(v[k]==num)w[k]++;
else if(num<v[k])
{
Insert(ls[k],num);
if(rnd[ls[k]]<rnd[k])
Rturn(k);
}
else
{
Insert(rs[k],num);
if(rnd[rs[k]]<rnd[k])
Lturn(k);
}
}
void Del(int &k,int num)
{
if(v[k]==num)
{
if(w[k]>){
w[k]--;
s[k]--;
return;
}
if(ls[k]*rs[k]==)
k=ls[k]+rs[k];
else if(rnd[ls[k]]<rnd[rs[k]])
Rturn(k),Del(k,num);
else
Lturn(k),Del(k,num);
}
else if(num<v[k]){
Del(ls[k],num);
s[k]--;
}
else{
Del(rs[k],num);
s[k]--;
}
}
void Find(int k,int num)
{
if(!k)return;
if(v[k]<=num){
tmp+=s[ls[k]]+w[k];
Find(rs[k],num);
}
else Find(ls[k],num);
}
}Tr; ///////////////////// /////////////////////线段树
int lowbit(int x)
{
return x&(-x);
}
void Bit_updata(int x,int v)
{
for(;x<=n+;x+=lowbit(x))
Tr.Insert(Tr.root[x],v);
}
void Bit_change(int x,int v)
{
for(;x<=n+;x+=lowbit(x))
Tr.Del(Tr.root[x],v);
}
void Bit_query(int x,int num)
{
for(;x;x-=lowbit(x))
Tr.Find(Tr.root[x],num);
}
/////////////////////////// ///////////////////////////树状数组
struct Bit
{ int a[];
int lowbit(int x)
{
return x&(-x);
}
int query(int x)
{
int ans = ;
for(;x;x-=lowbit(x))
ans+=a[x];
return ans;
}
void updata(int x,int v)
{
for(;x<;x+=lowbit(x))
a[x]+=v;
}
}bit,bit2; /////////////////////////// int main()
{
//freopen("a+b.in","r",stdin);
srand(time(NULL));
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(bit2.a,,sizeof(bit2.a));
Tr.init();
memset(bit.a,,sizeof(bit.a));
long long Res = ;
for(int i=;i<=n;i++)
{
a[i]=read();
Bit_updata(i,a[i]);
bit.updata(a[i],);
Res += (i-bit.query(a[i]-)-);
pos[a[i]]=i;
}
memset(bit.a,,sizeof(bit.a));
for(int i=;i<=n;i++)
bit.updata(i,),bit2.updata(i,);
for(int i=;i<=m;i++)
{
printf("%lld\n",Res);
int x;scanf("%d",&x);
long long ans1 = bit2.query(x)-;//总共有多少数比他小
Bit_query(pos[x],x);long long ans2 = tmp;tmp=;ans2--;//在他前面有多少比他小
long long ans3 = bit.query(pos[x])-;//在他前面一共有多少个数
long long Ans1 = ans3 - ans2;//前面有多少个数比他大
long long Ans2 = ans1 - ans2;//后面有多少个数比他小
//cout<<ans1<<" "<<ans2<<" "<<ans3<<endl;
//cout<<Ans1<<" "<<Ans2<<endl;
Res = Res-Ans1-Ans2;
Bit_change(pos[x],x);
bit2.updata(x,-);
bit.updata(pos[x],-);
}
}
}

UVA 11990 ``Dynamic'' Inversion 动态逆序对的更多相关文章

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

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

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

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

  3. UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)

    题目要求可转化为查询一个区间内有多少数比val大(或者小). 区间用线段树分解(logN),每个区间维护一rank树. rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离 ...

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

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

  5. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  6. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  7. BZOJ 3295: [Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3865  Solved: 1298[Submit][Sta ...

  8. Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2886  Solved: 924[Submit][Stat ...

  9. 【Luogu1393】动态逆序对(CDQ分治)

    [Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...

随机推荐

  1. LINUX启动ORACLE监听和服务

    可通过secureCRT或者telnet直接连 启动监听命令:lsnrctl start 成功启动后:sqlplus /nolog 回车 conn / as sysdba 回车 startup 回车 ...

  2. tomcat 调优

    1 总是遇到read time out ,socket什么的           <Executor name="tomcatThreadPool" namePrefix=& ...

  3. Oracle 手工清除回滚段的几种方法

    关于回滚段的问题,之前也小整理过一个,参考: Current online Redo 和 Undo 损坏的处理方法 http://blog.csdn.net/tianlesoftware/articl ...

  4. IO负载高的来源定位

    前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到IO负载的来源进程和来源文件导致无法进行相应的策略来解决问题. 这个现象在MySQ ...

  5. HDU 1671 Phone List(POJ 3630)

    Phone List Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. linux命令——scp 两台linux机器间文件或目录传输

    不同的Linux之间copy文件常用有3种方法: 第一种:ftp,也就是其中一台Linux安装ftpServer,这样可以另外一台使用ftp的client程序来进行文件的copy. 第二种:采用sam ...

  7. DzzOffice管理员登陆方法和管理员应用介绍

    DzzOffice的管理方式类似于windows的管理方式,是直接在桌面中,通过管理员应用进行系统中的所有管理里工作. 1.访问http://www.domain.com (你站点的访问地址) 2.点 ...

  8. NGUI的UIProgressBar使用裁剪方式而不是压缩方式的方法

    UIProgressBar默认的方式是压缩图片,而如果我们需要裁减图片,只需要将UIProgressBar的Foreground的UISprite的Type改为Filled就行了. 好几个“的”... ...

  9. 【C#】字符串与字符数组

    字符串与字符数组的相互转换. 字符串转换成字符数组: string ss="abcdefg"; char[] cc=ss.ToCharArray();     字符数组转换成字符串 ...

  10. java 最佳且开源的反编译工具

    1.jad:2.jode 很多gui的反编译工具(decafe,DJ,cavaJ)差不多都是基于jad和jode的.