codevs1688 求逆序对(权值线段树)
生活随笔
收集整理的這篇文章主要介紹了
codevs1688 求逆序对(权值线段树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1688 求逆序對
?
?時間限制: 1 s ?空間限制: 128000 KB ?題目等級 : 黃金 Gold 題解 ?查看運行結果 題目描述?Description給定一個序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我們稱之為逆序對,求逆序對的數目
?
數據范圍:N<=105。Ai<=105。時間限制為1s。
?
輸入描述?Input Description第一行為n,表示序列長度,接下來的n行,第i+1行表示序列中的第i個數。
輸出描述?Output Description所有逆序對總數.
樣例輸入?Sample Input4
3
2
3
2
樣例輸出?Sample Output3
?
/* 權值線段樹模板 首先我們更改線段樹葉子節點處存儲的內容,將其更改為權值,并且記錄對于一個權值x的個數。 那么我們首先構建一棵空樹, 對于每次插入的數字x,我們查找x+1到max區間的數字存在的個數,并將這個個數加入答案, 然后插入這個數字。最后輸出答案就可以了。。 */ #include<iostream> #include<cstdio> #include<cstring>#define N 200007using namespace std; int n,x; long long ans; struct tree {int l,r;long long sum; }tr[N<<2];void push_up(int now) {tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum; }void build(int now,int l,int r) {tr[now].l=l;tr[now].r=r;if(l==r) return;int mid=(tr[now].l+tr[now].r)>>1;build(now<<1,l,mid);build(now<<1|1,mid+1,r); }void insert(int now,int k) {if(tr[now].l==k && tr[now].l==tr[now].r) {tr[now].sum++;return;} int mid=(tr[now].l+tr[now].r)>>1;if(x>mid) insert(now<<1|1,k);if(x<=mid) insert(now<<1,k);push_up(now); }long long gets(int now,int l,int r) {if(tr[now].l>r||tr[now].r<l) return 0;if(tr[now].l==l&&tr[now].r==r)return tr[now].sum;int mid=(tr[now].l+tr[now].r)>>1;if(l>mid) return gets(now<<1|1,l,r);else if(r<=mid) return gets(now<<1,l,r);else return gets(now<<1,l,mid)+gets(now<<1|1,mid+1,r); }int main() {scanf("%d",&n);build(1,1,N);ans=0;for(int i=1;i<=n;i++){scanf("%d",&x);ans+=gets(1,x+1,N);insert(1,x);}printf("%lld\n",ans);return 0; }?
轉載于:https://www.cnblogs.com/L-Memory/p/7245029.html
總結
以上是生活随笔為你收集整理的codevs1688 求逆序对(权值线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么香蕉炒香肠会死人
- 下一篇: 烤箱为什么要用锡箔纸?