E.Divide Square(樹狀陣列/線段樹)(掃描線)
阿新 • • 發佈:2020-08-26
讓A,b序列中大小排名相對應即可
若A中第j大的位於i,則應該b中第j大位於i
證明:假如a1<a2,b1<b2
則排列方式有 a1,a2,b1,b2或 a1,a2,b2,b1那麼
對於這兩種情況上,平方並做差,即可得以上結論
然而大問題是這樣離散化後怎麼搞出交換幾次呢
離散化後
\(c_{a_i}\)=\(b_i\),然後若我們最後拍完序
定然\(c_i\)=i
也就是記錄了相同排名的值得對應關係
結果是要讓他們一一對應的
也就是上面的
拍完序後,然後就是相同位置對應了
其實也就是記錄了A中第i大的元素的位置和b中的對應位置
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int tree[100001]; struct num{ int v; int p; }a[100001],b[100001]; int n; const int mod = 99999997; int a1[100001]; int b1[100001]; int c[100001]; int q[100001]; bool cmp(num x,num y){ return x.v<y.v; } int lowbit(int x){ return x&-x; } void up(int x,int y){ while(x<=n){ tree[x]+=y; tree[x]%=mod; x+=lowbit(x); } } int find(int x){ int ans=0; while(x>=1){ ans+=tree[x]; ans%=mod; x-=lowbit(x); } return ans; } int ans; bool cmp1(const int &x,const int &y){ return q[x]>q[y]; } int main (){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&a[i].v); a[i].p=i; } for(int i=1;i<=n;++i){ scanf("%d",&b[i].v); b[i].p=i; } sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp); for(int i=1;i<=n;++i){ q[a[i].p]=b[i].p; } for(int i=n;i>=1;--i){ up(q[i],1); ans+=find(q[i]-1)%mod; ans%=mod; } cout<<(ans%mod+mod)%mod; return 0; }