题解 CF785E 【Anton and Permutation】

Owen_codeisking

2018-11-23 08:05:17

Solution

## 分块大法好!!!!! 考虑用块中在 $vector$ 中二分,边角暴力,$swap$ 两个元素就二分然后 $erase,insert$ 一下,时间复杂度为 $O(n\sqrt{n}\log n)$ 个人经验:以下两种分块写法是不等价的 写法一: ```cpp for(int i=1;i<=blo;i++){ L[i]=(i-1)*blo+1,R[i]=i*blo; for(int j=L[i];j<=R[i];j++) pos[j]=i,v[i].push_back(j); } if(blo*blo!=n){ int i=blo+1;L[i]=(i-1)*blo+1,R[i]=n; for(int j=L[i];j<=R[i];j++) pos[j]=i,v[i].push_back(j); } for(int i=1;i<=n;i++) a[i]=i; ``` 写法二: ```cpp for(int i=1;i<=blo;i++){ L[i]=(i-1)*blo+1,R[i]=i*blo; for(int j=L[i];j<=R[i];j++) v[i].push_back(j); } if(blo*blo!=n){ int i=blo+1;L[i]=(i-1)*blo+1,R[i]=n; for(int j=L[i];j<=R[i];j++) v[i].push_back(j); } for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1,a[i]=i; ``` 注意:写法二的 $pos[i]$ 是错的,因为最后一块的大小可以超过 $\sqrt{n}$ 的!!! $Code\ Below:$ ```cpp #include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=200000+10; const int inf=0x3f3f3f3f; int n,m,a[maxn],pos[maxn],L[maxn],R[maxn],cnt[maxn],blo;ll ans; vector<int> v[500]; inline int read(){ register int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return (f==1)?x:-x; } void update(int l,int r){ int p=pos[l],q=pos[r]; if(p < q){ v[p].erase(lower_bound(v[p].begin(),v[p].end(),a[l])); v[p].insert(upper_bound(v[p].begin(),v[p].end(),a[r]),a[r]); v[q].erase(lower_bound(v[q].begin(),v[q].end(),a[r])); v[q].insert(upper_bound(v[q].begin(),v[q].end(),a[l]),a[l]); } swap(a[l],a[r]); } ll query(int l,int r,int k){ if(l > r) return 0; int p=pos[l],q=pos[r];ll ans=0,num; if(p+1>=q){ for(int i=l;i<=r;i++) if(a[i]<k) ans++; } else { for(int i=l;i<=R[p];i++) if(a[i]<k) ans++; for(int i=L[q];i<=r;i++) if(a[i]<k) ans++; for(int i=p+1;i<=q-1;i++){ num=upper_bound(v[i].begin(),v[i].end(),k)-v[i].begin(); ans+=num; } } return ans; } int main() { n=read(),m=read();blo=sqrt(n); for(int i=1;i<=blo;i++){ L[i]=(i-1)*blo+1,R[i]=i*blo; for(int j=L[i];j<=R[i];j++) pos[j]=i,v[i].push_back(j); } if(blo*blo!=n){ int i=blo+1;L[i]=(i-1)*blo+1,R[i]=n; for(int j=L[i];j<=R[i];j++) pos[j]=i,v[i].push_back(j); } for(int i=1;i<=n;i++) a[i]=i; int l,r; for(int i=1;i<=m;i++){ l=read(),r=read(); if(l>r) swap(l,r); if(l==r) printf("%I64d\n",ans); else { ans+=2*query(l+1,r-1,a[r])-(r-l-1); ans+=(r-l-1)-2*query(l+1,r-1,a[l]); ans+=(a[l]<a[r])?1:(a[l]>a[r])?-1:0; update(l,r); printf("%I64d\n",ans); } } return 0; } ```