[CF540E] Infinite Inversions - 離散化,線段樹
阿新 • • 發佈:2020-08-27
Description
現在有一個由所有正整陣列成的無限遞增序列。對這個序列執行 \(n\) 次交換操作。每次一個操作,給出兩個整數 \(a,b\),交換位置 \(a\) 和 \(b\) 處的元素。在所有操作結束後,輸出最終序列的逆序對個數。
Solution
離散化,利用左閉右開區間 \([l,r)\) 作為單個結點
離散化後直接交換,交換後用按照順序從小到大掃一遍,線段樹統計即可
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2000005; int n,t1,t2,ind; map<int,int> mp; vector <int> vec_value; struct Node { int l,r,id; int len() { return r-l; } }; vector <Node> vec; map<int,int> single_index; int ida[N],idb[N]; int a[N]; void modify(int p,int l,int r,int pos,int key) { a[p]+=key; if(l<r) { if(pos<=(l+r)/2) modify(p*2,l,(l+r)/2,pos,key); else modify(p*2+1,(l+r)/2+1,r,pos,key); } } int query(int p,int l,int r,int ql,int qr) { if(l>qr || r<ql) return 0; if(l>=ql && r<=qr) return a[p]; return query(p*2,l,(l+r)/2,ql,qr) + query(p*2+1,(l+r)/2+1,r,ql,qr); } signed main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) { cin>>t1>>t2; mp[t1]++; mp[t2]++; ida[i]=t1; idb[i]=t2; } for(auto &i:mp) { vec_value.push_back(i.first); } if(vec_value.size()) { int i=0; vec.push_back({vec_value[i],vec_value[i]+1}); single_index[vec_value[i]]=vec.size()-1; } for(int i=1;i<vec_value.size();i++) { if(vec_value[i]>vec_value[i-1]+1) { vec.push_back({vec_value[i-1]+1,vec_value[i]}); } vec.push_back({vec_value[i],vec_value[i]+1}); single_index[vec_value[i]]=vec.size()-1; } int m=vec.size(); for(int i=0;i<m;i++) { vec[i].id=i+1; } for(int i=1;i<=n;i++) { int p=single_index[ida[i]], q=single_index[idb[i]]; swap(vec[p],vec[q]); } /*for(int i=1;i<=m;i++) { cout<<vec[i-1].l<<" "<<vec[i-1].r<<endl; } cout<<endl;*/ int ans=0; /* Brute force version for(int i=1;i<=m;i++) { for(int j=i+1;j<=m;j++) { if(vec[i-1].l > vec[j-1].l) { ans+=vec[i-1].len()*vec[j-1].len(); } } }*/ for(int i=0;i<m;i++) { ans+=query(1,1,m,vec[i].id+1,m)*vec[i].len(); modify(1,1,m,vec[i].id+1,vec[i].len()); } cout<<ans<<endl; }