这道题本质上是一个二维数点的模板,并且是强制在线的,因此可以用树套树,但是我不会树套树
可以想到一个暴力的方法,就是分块,分完块后,每块动态维护一个vector,因为我们发现,交换两个数后,只有在l-r区间内并且范围在a[l]-a[r]之间的数才会收到影响
这样我们就可以通过vector查找范围
分块这东西,还是很牛逼的,因为可以发现,每块不超过sqrt(n)并且块的数量也不超过他
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<string> #include<map> #include<vector> using namespace std; typedef long long ll; const int N=1e6+10; const int mod=1e9+7; vector<int> num[10005]; int n; int a[N]; int block; void init(){ block=sqrt(n); for(int i=1;i<=n;i++){ a[i]=i; int pos=(i-1)/block+1; num[pos].push_back(i); } } ll work(int l,int r){ if(l==r) return 0; int idx1=(l-1)/block+1; int idx2=(r-1)/block+1; int x=a[l],y=a[r]; int pos=find(num[idx1].begin(),num[idx1].end(),x)-num[idx1].begin(); num[idx1][pos]=y; pos=find(num[idx2].begin(),num[idx2].end(),y)-num[idx2].begin(); num[idx2][pos]=x; sort(num[idx1].begin(),num[idx1].end()); sort(num[idx2].begin(),num[idx2].end()); ll ans=0; int f; if(x>y){ swap(x,y); f=-1; } else{ f=1; } int i; if(idx1==idx2){ for(i=l+1;i<r;i++){ if(a[i]>x&&a[i]<y) ans++; } } else{ for(i=l+1;i<=idx1*block;i++) if(a[i]>x&&a[i]<y) ans++; for(i=idx1+1;i<idx2;i++){ ans+=upper_bound(num[i].begin(), num[i].end(), y) - lower_bound(num[i].begin(), num[i].end(), x); } for(i=(idx2-1)*block+1;i<r;i++) if(a[i]>x&&a[i]<y) ans++; } swap(a[l],a[r]); return (2*ans+1)*f; } int main(){ int q; cin>>n>>q; ll ans=0; init(); while(q--){ int l,r; cin>>l>>r; if(l>r) swap(l,r); ans+=work(l,r); cout<<ans<<endl; } }