P3531 [POI2012]LIT-Letters(樹狀陣列||逆序對)
阿新 • • 發佈:2021-10-02
轉換成求逆序對的問題。
如果沒有重複的字母,顯然是一一對應,用第二個串裡對應字元的下標i作為position,然後得到一個position的序列,求這個序列的逆序對個數即為步數。
(這個position代表一種相對前後的關係,我們只需要處理後使序列中沒有逆序對即可。)
當有重複的時候,我們發現,給它一種對應關係即可:第一個a對應第一個a....以此類推。
注意樹狀陣列中不能出現0,否則lowbit會為0,使其陷入死迴圈。
樹狀陣列求逆序對時可以從後往前,然後add進當前值後,查詢當前樹狀陣列中嚴格小於該值的數即可(sum:1~b[i]-1)。(注意下標為數值,存的為個數)
#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; const int N=1000005; typedef long long ll; int n; ll ans; string a,b; vector<int> v[N]; int id[N],cnt[N],t[N]; int read(){ int num=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ num=num*10+c-'0'; c=getchar(); } return num*f; } int lowbit(int x){ return x&(-x); } void add(int x){ for(;x<=n;x+=lowbit(x)){ t[x]+=1; } } int ask(int x){ int res=0; for(;x;x-=lowbit(x)){ res+=t[x]; } return res; } int main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); n=read(); cin>>a>>b; for(int i=0;i<n;i++){ v[b[i]-'A'].push_back(i); } for(int i=0;i<n;i++){ id[i+1]=v[a[i]-'A'][cnt[a[i]-'A']]+1; cnt[a[i]-'A']++; } for(int i=n;i>=1;i--){ add(id[i]); ans+=ask(id[i]-1); } printf("%lld",ans); return 0; }