[bzoj2789]Letters
考虑A中第i次出现的j字符,最终位置一定是在B中第i次出现的j字符的位置,然后即求逆序对数量,cdq/线段树即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 int n,a[N],c[N],nex[N],f[N<<2]; 8 long long ans; 9 char s[N]; 10 void update(int k,int l,int r,int x){ 11 if (l==r){ 12 f[k]++; 13 return; 14 } 15 if (x<=mid)update(L,l,mid,x); 16 else update(R,mid+1,r,x); 17 f[k]=f[L]+f[R]; 18 } 19 int query(int k,int l,int r,int x,int y){ 20 if ((l>y)||(x>r))return 0; 21 if ((x<=l)&&(r<=y))return f[k]; 22 return query(L,l,mid,x,y)+query(R,mid+1,r,x,y); 23 } 24 int main(){ 25 scanf("%d%s",&n,s); 26 memset(c,-1,sizeof(c)); 27 for(int i=n-1;i>=0;i--){ 28 nex[i]=c[s[i]-'A']; 29 c[s[i]-'A']=i; 30 } 31 scanf("%s",s); 32 for(int i=0;i<n;i++){ 33 a[c[s[i]-'A']]=i; 34 c[s[i]-'A']=nex[c[s[i]-'A']]; 35 } 36 for(int i=0;i<n;i++){ 37 ans+=query(1,0,n-1,a[i],n-1); 38 update(1,0,n-1,a[i]); 39 } 40 printf("%lld",ans); 41 }