统计逆序对--函数式线段树

来源:互联网 发布:莎莎源码是什么意思 编辑:程序博客网 时间: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

转载请注明出处

原创粉丝点击