统计逆序对--函数式线段树
来源:互联网 发布:莎莎源码是什么意思 编辑:程序博客网 时间:2024/06/13 23:20
[题目描述]
众所周知,lyp喜欢以用各种方式折磨别人为乐,这次,他趁 wars不在时在他的电脑上
挂了一把神奇的锁,这把锁需要一串巨长无比的数字密码才可以解开,这 个密码由 lyp 自
己保管,这样 wars 就没法 Kingdom Rush 了。但 wars 设法从 lyp 的脑袋中挖出了有关密码
的信息,这些信息是一列非负整数{An}。而解开密 码锁的方式是首先输入这列这数的逆序
对数,而后依次会在 wars的电脑屏幕上显示两个数字 p,q,你则需要输入将整数列中第 p个
整数替换成q后整个数列的逆序 对数,这样的询问会有 m个。当然,这样的替换只对这一
次的询问有效。现在 wars急着去打Kingdom Rush,因此将打开电脑的任务交给了你。
[数据范围]
n<=50000,m<=50000
0<=序列的每一元素(包括询问中的)<=100000
保证询问合法。
[题解]
这道题目可以用离线算法做.将询问排序后就可以用一个树状数组搞出来了.
由于解决这道问题要牵扯到查询区间内某一范围内的数的个数,所以也可以用函数式线段树(不过常数被树状数组完爆).总之,这还是一道不错的函数式线段树基础题的.
讲一下函数式的思想:由于线段树每次修改只要改log(n)个节点,所以每次新建log(n)个节点即可.因为每次root都会被更新,所以直接开一个数组记住每次的root,查询时直接自顶向下的查询即可.
图就不画了(太丑了),不过这东西实现起来还是比较容易的,代码也不长.唯一的缺点是需要的空间太多了.
Code:
program lyp;type int=longint;const null=-1;var i,j,k,m,ans,n,tot,x,y:int; s,ls,rs,ll,rr:array[0..2000000]of int; root,a:array[0..50000]of int;function build(l,r:int):int;var mid,now:int;begin if l=r-1 then begin inc(tot);ls[tot]:=null;rs[tot]:=null;ll[tot]:=l;rr[tot]:=r; exit(tot); end; mid:=(l+r)>>1; inc(tot);now:=tot; ll[tot]:=l;rr[tot]:=r; ls[now]:=build(l,mid); rs[now]:=build(mid,r); exit(now);end;function ins(x,y:int):int;var mid:int;begin if ll[x]=rr[x]-1 then begin inc(tot);s[tot]:=s[x]+1; ls[tot]:=null;rs[tot]:=null; ll[tot]:=ll[x];rr[tot]:=rr[x]; exit(tot); end; if ll[x]>=rr[x] then exit; mid:=(ll[x]+rr[x])>>1; inc(tot);ins:=tot; ls[tot]:=ls[x];rs[tot]:=rs[x]; ll[tot]:=ll[x];rr[tot]:=rr[x]; if y>mid then rs[ins]:=ins(rs[x],y) else ls[ins]:=ins(ls[x],y); s[ins]:=s[ls[ins]]+s[rs[ins]];end;function ask(r1,r2,l,r:int):int;var mid:int;begin if(r1=r2)then exit(0); if(l<=ll[r1])and(rr[r1]<=r)then exit(s[r2]-s[r1]); ask:=0;mid:=(ll[r1]+rr[r1])>>1; if(r>mid)then ask:=ask+ask(rs[r1],rs[r2],l,r); if(l<mid)then ask:=ask+ask(ls[r1],ls[r2],l,r);end;begin assign(input,'lyp.in');reset(input); assign(output,'lyp.out');rewrite(output); root[0]:=build(0,100000); read(n,m); for i:=1 to n do begin read(a[i]); inc(a[i]); root[i]:=ins(root[i-1],a[i]); ans:=ans+ask(root[0],root[i],a[i],100000); end; writeln(ans); for i:=1 to m do begin read(x,y);inc(y); if y>a[x]then k:=-ask(root[0],root[x-1],a[x],y)+ask(root[x],root[n],a[x]-1,y-1) else k:=ask(root[0],root[x-1],y,a[x])-ask(root[x],root[n],y-1,a[x]-1); writeln(ans+k); end; close(input);close(output);end.
BY QW
转载请注明出处
- 统计逆序对--函数式线段树
- HDU 1394 线段树统计逆序对 解题报告
- 求逆序对(线段树版)
- 线段树 CodeForces 61E 逆序对
- 【NOIP2013】火柴排队 线段树+逆序对
- 【CDOJ 383】Japan 【线段树+逆序对】
- hdu 5493 Queue(逆序对,线段树)
- POJ 2188线段树求逆序对
- hdu 1394 线段树求逆序对
- 逆序对—权值线段树
- inv 线段树,逆序对,离散化
- 11087 统计逆序对
- 统计逆序对
- 统计数组中的逆序对
- 统计数组的逆序对
- 【51Nod1779】逆序对统计
- NOIP模拟题 2016.11.8 (2) [线段树] [动态逆序对] [矩阵快速幂] [数论] [欧拉函数]
- hdu 1394 Minimum Inversion Number(线段树求逆序对)
- CGLIB入门编程例子
- AfxBeginThread
- ubuntu在gnome class中alt+tab功能不能用
- C#设置winform窗口无法移动
- MYSQL双主同步故障
- 统计逆序对--函数式线段树
- socket programming
- 2012百度广州站软开、运维面试题目
- iPhone wifi使用socket连接Internet
- php 解析 xml simplexml_load_string()返回的是一个对象
- Servlet
- 在没有类的情况下,JavaScript如何创建对象、实现继承?
- poj1655-又是一道简单而又纠结的题目
- User-Managed Backups 用户管理的备份