uva11990 动态逆序对
生活随笔
收集整理的這篇文章主要介紹了
uva11990 动态逆序对
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這題說的是給了一個數組,按照他給的順序依次刪除數,在刪除之前輸出此時的逆序對個數
我們用Fenwick樹 維護這整個數列, C[i]是一個 treap的頭, 管理了在樹狀數組中 能影響他的點,然后我們用名次樹去計算 在C[i]下小于等于要刪除的那個數的個數就ok了。
#include <iostream> #include <algorithm> #include <string.h> #include <vector> #include <cstdio> #include <stdlib.h> using namespace std; const int maxn=200005; struct Node {Node *ch[2];int r;int s;int v;int vloc;int cmp(int x)const{if(x==v)return -1;return x<v?0:1;}void maintain(){s=ch[0]->s+ch[1]->s+vloc;} }; Node *null=new Node(); void rotate(Node *&o, int d) {Node *k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;o->maintain();k->maintain(); o=k; } void insert(Node *&o,int x) {if(o==null){o=new Node();o->ch[0]=o->ch[1]=null; o->v=x; o->r=rand();o->vloc=1;o->s=1;}else{int d=o->cmp(x);if(d==-1){o->vloc+=1;}else{insert(o->ch[d],x);if( o->ch[d]->r > o->r) rotate(o,d^1);}}o->maintain(); } void remove(Node *&o, int x) {int d=o->cmp(x);if(d==-1){if(o->vloc > 1){o->vloc-=1;}else if(o->ch[0]==null)o=o->ch[1];else if(o->ch[1]==null) o=o->ch[0];else{int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0 ;rotate(o,d2); remove(o->ch[d2],x);}}else remove(o->ch[d],x);if(o!=null)o->maintain(); } int find(Node *o,int x) {int num=0;while(o!=null){int d=o->cmp(x);if(d==-1){num += o->ch[0]->s + o->vloc ;break;}else if(d==1){num+=o->ch[0]->s+o->vloc;o=o->ch[1];}else{o=o->ch[0];}}return num; } Node *C[maxn]; int cc[maxn],A[maxn]; int lowbit(int x) {return (-x)&x; } void init(int n) {for(int i=0; i<=n; i++)C[i]=null,cc[i]=0; } int N,M; void add1(int x, int v) {while(x<=N){cc[x]+=v;x+=lowbit(x);} } int sum1(int x){int ans=0;while(x>0){ans+=cc[x];x-=lowbit(x);}return ans; } void delet(int x,int v) {while(x<=N){remove(C[x],v);x+=lowbit(x);} } int summ(int x,int v) {int ans=0;while(x>0){ans+=find(C[x],v);x-=lowbit(x);}return ans; } int main() {null->s=0;while(scanf("%d%d",&N,&M)==2){init(N);long long ans=0;for(int i=1; i<=N; i++){int d;scanf("%d",&d);A[d]=i;ans+=sum1(N)-sum1(d);add1(d,1);int loc=i;while(loc<=N){insert(C[loc],d); loc+=lowbit(loc);}}for(int i=1; i<=M; i++){int d;printf("%lld\n",ans);scanf("%d",&d);int s1xiaoyu=summ(A[d],d);int ss1=sum1(A[d]);ans-=(ss1-s1xiaoyu);int s2xiaoyu=summ(N,d);ans-=s2xiaoyu-s1xiaoyu;add1(A[d],-1);delet(A[d],d);}}return 0; } /* 5 4 1 5 3 4 2 5 1 4 2 */ View Code?
轉載于:https://www.cnblogs.com/Opaser/p/4906530.html
總結
以上是生活随笔為你收集整理的uva11990 动态逆序对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js中的true,false盲点
- 下一篇: Git更新到最新版本