C85 树状数组+逆序对 P1966 [NOIP2013 提高组] 火柴排队
视频链接:271 树状数组+逆序对 P1966 [NOIP2013 提高组] 火柴排队_哔哩哔哩_bilibili
Luogu P1966 [NOIP2013 提高组] 火柴排队
// 逆序对+树状数组 O(nlogn) #include<cstdio> #include<algorithm> using namespace std; #define lowb(x) (x&-x) const int N=100010, mod=99999997; struct node{ int val,pos; //值,位置 bool operator<(node b){ return val<b.val; } }a[N],b[N]; int n,ans,s[N],c[N]; //c:位置映射 void change(int x,int k){ //向后修 while(x<=n) s[x]=(s[x]+k)%mod,x+=lowb(x); } int query(int x){ //向前查 int t=0; while(x) t=(t+s[x])%mod,x-=lowb(x); return t; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].pos=i; for(int i=1;i<=n;i++) scanf("%d",&b[i].val),b[i].pos=i; sort(a+1,a+n+1); sort(b+1,b+n+1); for(int i=1;i<=n;i++) c[a[i].pos]=b[i].pos; for(int i=n;i;i--){ //从后面找<ci的个数 ans=(ans+query(c[i]-1))%mod; change(c[i],1); } printf("%d",ans); }
// 逆序对+归并排序 O(nlogn) #include<cstdio> #include<algorithm> using namespace std; const int N=100010, mod=99999997; struct node{ int val,pos; //值,位置 bool operator<(node b){ return val<b.val; } }a[N],b[N]; int n,ans,c[N],d[N]; //c:位置映射 void merge(int l,int r){ if(l>=r) return; int mid=l+r>>1; merge(l,mid); merge(mid+1,r); //拆分 int i=l,j=mid+1,k=l; //合并 while(i<=mid && j<=r){ if(c[i]<=c[j]) d[k++]=c[i++]; else d[k++]=c[j++], ans=(ans+mid-i+1)%mod; } while(i<=mid) d[k++]=c[i++]; while(j<=r) d[k++]=c[j++]; for(i=l; i<=r; i++) c[i]=d[i]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i].val),a[i].pos=i; for(int i=1;i<=n;i++) scanf("%d",&b[i].val),b[i].pos=i; sort(a+1,a+n+1); sort(b+1,b+n+1); for(int i=1;i<=n;i++) c[a[i].pos]=b[i].pos; merge(1,n); printf("%d",ans); }