【分块】【树套树】bzoj2141 排队
2014-09-12 15:21
369 查看
考虑暴力更新的情况,设swap的是L,R位置的数。
swap之后的逆序对数应该等于:
之前的逆序对数
+[L+1,R-1]中比 L位置的数 大的数的个数
-[L+1,R-1]中比 L位置的数 小的数的个数
-[L+1,R-1]中比 R位置的数 大的数的个数
+[L+1,R-1]中比 R位置的数 小的数的个数
并且若L位置的数>R位置的数,逆序对数--;反之,逆序对数++。
分块,对每个块内部进行sort,这样可以二分,在O(log(sqrt(n))的时间内求得某个块内比某个数大/小的数的个数。所以每次更新是O(sqrt(n)*log(sqrt(n))的。
若L和R所在的块相同或相邻时,直接暴力更新即可。
要用树状数组或归并排序求得初始答案。
要注意数据是可重的,所以要打时间戳。
所以为了lower_bound/upper_bound,要定义两套比较法则,一套双关键字,一套单关键字。
swap之后的逆序对数应该等于:
之前的逆序对数
+[L+1,R-1]中比 L位置的数 大的数的个数
-[L+1,R-1]中比 L位置的数 小的数的个数
-[L+1,R-1]中比 R位置的数 大的数的个数
+[L+1,R-1]中比 R位置的数 小的数的个数
并且若L位置的数>R位置的数,逆序对数--;反之,逆序对数++。
分块,对每个块内部进行sort,这样可以二分,在O(log(sqrt(n))的时间内求得某个块内比某个数大/小的数的个数。所以每次更新是O(sqrt(n)*log(sqrt(n))的。
若L和R所在的块相同或相邻时,直接暴力更新即可。
要用树状数组或归并排序求得初始答案。
要注意数据是可重的,所以要打时间戳。
所以为了lower_bound/upper_bound,要定义两套比较法则,一套双关键字,一套单关键字。
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; struct Point{int v,p;Point(const int &a,const int &b){v=a;p=b;}Point(){}}; bool operator < (const Point &a,const Point &b){return a.v<b.v;}//单关键字比较 bool operator > (const Point &a,const Point &b){return a.v>b.v;} bool operator == (const Point &a,const Point &b){return a.v==b.v ? true : false;} bool cmp(const Point &a,const Point &b){return a.v!=b.v ? a.v<b.v : a.p<b.p;}//双关键字比较 Point b[20001],a[20001],c[20001]; int n,sz,l[145],r[145],sum,num[20001],ans,x,y,m,mid,en; int Res,Num;char C,CH[20]; inline int G() { Res=0;C='*'; while(C<'0'||C>'9')C=getchar(); while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();} return Res; } inline void P(int x) { if(!x){putchar('0');putchar('\n');return;} Num=0;while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); putchar('\n'); } void LiSan() { n=G(); for(int i=1;i<=n;i++){b[i].v=G();b[i].p=i;} sort(b+1,b+n+1,cmp); for(int i=1;i<=n;i++) { if(b[i].v!=b[i-1].v)en++; a[b[i].p].v=en; a[b[i].p].p=i; } } //树状数组求出初始答案。 int D[20001];inline int lowbit(const int &x){return x&(-x);} inline int getsum(int x){int res=0;while(x>0){res+=D[x];x-=lowbit(x);}return res;} inline void add(int x,const int &d){while(x<=n){D[x]+=d;x+=lowbit(x);}} void Get_First_Ans() {for(int i=1;i<=n;i++){add(a[i].v,1);ans+=(i-getsum(a[i].v));} P(ans);} void makeblock() { sz=sqrt(n); for(sum=1;sum*sz<n;sum++) { l[sum]=(sum-1)*sz+1;r[sum]=sum*sz; for(int i=l[sum];i<=r[sum];i++) num[i]=sum; } l[sum]=sz*(sum-1)+1;r[sum]=n; for(int i=l[sum];i<=r[sum];i++) num[i]=sum; } void Sort_Each_Block() {for(int i=1;i<=n;i++)c[i]=a[i]; for(int i=1;i<=sum;i++)sort(a+l[i],a+r[i]+1,cmp);} inline int Query(const int &L,const int &R) { swap( a[lower_bound(a+l[num[L]],a+r[num[L]]+1,c[L],cmp) - a ] , a[lower_bound(a+l[num[R]],a+r[num[R]]+1,c[R],cmp)- a ]);//必须双关键字比较 sort(a+l[num[L]],a+r[num[L]]+1,cmp); sort(a+l[num[R]],a+r[num[R]]+1,cmp); int cnt=0; if(c[L].v<c[R].v)cnt=1; else if(c[L].v>c[R].v)cnt=-1; swap(c[L],c[R]); if(num[L]+1>=num[R]) for(int i=L+1;i<=R-1;i++) {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--; if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;} else { for(int i=L+1;i<=r[num[L]];i++) {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--; if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;} for(int i=l[num[R]];i<=R-1;i++) {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--; if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;} for(int i=num[L]+1;i<=num[R]-1;i++) { cnt+=( (a+r[i]+1) - upper_bound(a+l[i],a+r[i]+1,c[R]) );//必须单关键字比较 cnt-=( lower_bound(a+l[i],a+r[i]+1,c[R]) - (a+l[i]) ); cnt-=( (a+r[i]+1) - upper_bound(a+l[i],a+r[i]+1,c[L]) ); cnt+=( lower_bound(a+l[i],a+r[i]+1,c[L]) - (a+l[i]) ); } } ans+=cnt;return ans; } int main() { LiSan();Get_First_Ans();makeblock();Sort_Each_Block();m=G(); for(int i=1;i<=m;i++){x=G();y=G();if(x>y)swap(x,y);P(Query(x,y));} return 0; }
相关文章推荐
- [BZOJ2141]排队(分块+树状数组求逆序对)
- [BZOJ]2141: 排队 分块+树状数组
- bzoj2141 排队 分块
- Bzoj 2141: 排队 分块,逆序对,树状数组
- BZOJ 2141 排队 分块
- [BZOJ2141]排队(分块)
- bzoj2141: 排队(树套树 或 分块)
- 【bzoj2141】排队 分块+树状数组
- bzoj 2141 : 排队 分块
- [BZOJ] 2141 - Atlantis - 排队 - 树状数组求逆序对 - 分块求区间比 k 小
- BZOJ2141 排队(分块)
- bzoj 2141 排队 【分块】
- BZOJ 2141 排队 分块+树状数组,详细题解
- BZOJ_2141_排队_树状数组+分块
- 【BZOJ2141】排队 树状数组+分块
- 【BZOJ 2141】排队【分块+Treap】
- BZOJ 2141 排队 分块+树状数组
- bzoj2141: 排队(分块+树状数组)
- Bzoj2141: 排队
- bzoj2141 排队