uva11990 - ``Dynamic'' Inversion(线段树套树状数组+分块)
2015-05-20 08:29
543 查看
题意:给出一个1,2,...,n的一个排列,然后删除一些数,每次删除之前,输出当前的逆序对数
思路:维护两个值,tree表示当前层,每一个线段树区间的树状数组,维护已经删除了多少个数,order维护,每一个线段树区间排好序的数列
每次输出答案后,进行更新,首先把当前这个数位置之前大于他的减掉,后面小于他的减掉,然后把这个位置标记为删除掉过
目前分块做法处于WA阶段,不知道错哪了
思路:维护两个值,tree表示当前层,每一个线段树区间的树状数组,维护已经删除了多少个数,order维护,每一个线段树区间排好序的数列
每次输出答案后,进行更新,首先把当前这个数位置之前大于他的减掉,后面小于他的减掉,然后把这个位置标记为删除掉过
/* *线段树套树状数组 *gaolee */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=200010; int N,M; int tree[30][maxn]; int order[30][maxn]; int X[maxn],tmp[maxn]; LL ans; void add(int *s,int x,int n,int val) { while(x<=n) { s[x]+=val; x+=(x&(-x)); } } int getsum(int *s,int x,int n) { int sum=0; while(x>n) { sum+=s[x]; x-=(x&(-x)); } return sum; } void build(int o,int l,int r,int d) { for(int i=l;i<=r;i++) order[d][i]=order[d-1][i],tree[d][i]=0; if(l==r)return ; int mid=(l+r)>>1; build(o<<1,l,mid,d+1); build(o<<1|1,mid+1,r,d+1); sort(order[d]+l,order[d]+r+1); } int bitser(int a,int b,int d,int v) { int l = a,r = b,md; while(l < r){ md = (l + r) >> 1; if(order[d][md]>=v)r = md; else l = md + 1; } if(order[d][l]>v)--l; return l; } void query(int o,int l,int r,int q1,int q2,int x,int d,int flag) { if(q1<=l&&r<=q2) { int k=lower_bound(order[d]+l,order[d]+r+1,x)-order[d]; if(order[d][k]>x||k>r)k--; int t=getsum(tree[d],k,l-1); if(!flag) { k=r-k; t=getsum(tree[d],r,l-1)-t; } else k-=l-1; ans-=k-t; return ; } if(l>=r)return ; int mid=(l+r)>>1; if(q1<=mid)query(o<<1,l,mid,q1,q2,x,d+1,flag); if(q2>mid)query(o<<1|1,mid+1,r,q1,q2,x,d+1,flag); } void update(int o,int l,int r,int pos,int x,int d) { if(l==r) { add(tree[d],l,r,1); return ; } if(l>=r)return ; int mid=(l+r)>>1; if(pos<=mid)update(o<<1,l,mid,pos,x,d+1); else update(o<<1|1,mid+1,r,pos,x,d+1); int k=lower_bound(order[d]+l,order[d]+r+1,x)-order[d]; add(tree[d],k,r,1); } int main() { while(scanf("%d%d",&N,&M)!=EOF) { ans=0; memset(tmp,0,sizeof(tmp)); for(int i=1;i<=N;i++) { scanf("%d",&order[0][i]); X[order[0][i]]=i; ans+=(i-1-getsum(tmp,order[0][i],0)); add(tmp,order[0][i],N,1); } build(1,1,N,1); while(M--) { int x; scanf("%d",&x); printf("%lld\n",ans); if(ans) { query(1,1,N,1,X[x]-1,x,1,0); query(1,1,N,X[x]+1,N,x,1,1); update(1,1,N,X[x],x,1); } } } return 0; }
目前分块做法处于WA阶段,不知道错哪了
/* *分块 *gaolee */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=200010; const int maxm=4010; int N,M; int A[maxn],pos[maxn],tmp[maxn]; int size; int block[maxm][maxm]; int st[maxn],vis[maxn]; LL ans; void add(int *s,int x,int n,int val) { while(x<=n) { s[x]+=val; x+=(x&(-x)); } } int getsum(int *s,int x,int n) { int sum=0; while(x>n) { sum+=s[x]; x-=(x&(-x)); } return sum; } void init() { size=int(sqrt(N)); int num=0,j=0; for(int i=0;i<N;i++) { block[num][j]=A[i]; if(++j==size){num++,j=0;} } for(int i=0;i<num;i++)sort(block[i],block[i]+size); if(j)sort(block[num],block[num]+j); for(int i=0;i<=num;i++)st[i]=i*size; } void QueryMax(int l,int r,int x) { int xpos=l/size,ypos=r/size; if(xpos==ypos) { for(int i=l;i<=r;i++) if(!vis[i]&&A[i]>x)ans--; } else { for(int i=l;i<(xpos+1)*size;i++) if(!vis[i]&&A[i]>x)ans--; for(int i=ypos*size;i<=r;i++) if(!vis[i]&&A[i]>x)ans--; for(int i=xpos+1;i<ypos;i++) if(st[i]<(i+1)*size) ans-=(i+1)*size-(lower_bound(block[i]+st[i],block[i]+size,x)-block[i]); } } void QueryMin(int l,int r,int x) { int xpos=l/size,ypos=r/size; if(xpos==ypos) { for(int i=l;i<=r;i++) if(!vis[i]&&A[i]<x)ans--; } else { for(int i=l;i<(xpos+1)*size;i++) if(!vis[i]&&A[i]<x)ans--; for(int i=ypos*size;i<=r;i++) if(!vis[i]&&A[i]<x)ans--; for(int i=xpos+1;i<ypos;i++) if(st[i]<(i+1)*size) ans-=lower_bound(block[i]+st[i],block[i]+size,x)-block[i]-st[i]; } } void update(int x,int val) { int bpos=x/size; int p=0; while(p<size&&block[bpos][p]<val)p++; if(p==size)p--;block[bpos][p]=-1; while(p>0&&block[bpos][p]<block[bpos][p-1]) { swap(block[bpos][p],block[bpos][p-1]),p--; } st[bpos]++; } int main() {freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M)!=EOF) { ans=0; memset(tmp,0,sizeof(tmp)); for(int i=1;i<=N;i++) { scanf("%d",&A[i]); ans+=(i-1-getsum(tmp,A[i],0)); add(tmp,A[i],N,1); } for(int i=0;i<N;i++) { A[i]=A[i+1]; A[i]--; pos[A[i]]=i; } memset(vis,0,sizeof(vis)); init(); while(M--) { int x; scanf("%d",&x); x--; printf("%lld\n",ans); int X=pos[x]/size; if(ans) { if(X*size-1>0)QueryMax(0,X*size-1,x); if((X+1)*size<N)QueryMin((X+1)*size,N-1,x); for(int i=X*size;i<pos[x];i++) if(!vis[i]&&A[i]>x)ans--; for(int i=pos[x]+1;i<min((X+1)*size,N);i++) if(!vis[i]&&A[i]<x)ans--; update(pos[x],x); vis[pos[x]]=1; } } } return 0; }
相关文章推荐
- Uva 11990 "Dynamic" Inversion(树状数组 + 数据结构分块)
- spoj 861 SWAPS & uva 11990 "Dynamic'' Inversion(动态维护逆序对)
- 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树
- [Uva 11990] "Dynamic" Inversion (二维分块)
- UVA 11990 ``Dynamic'' Inversion (分块 )
- 树状数组求第K小值 (spoj227 Ordering the Soldiers && hdu2852 KiKi's K-Number)
- 线段树(询问、插入)&树状数组POJ2352Starts解题报告
- HDOJ 1166 敌兵布阵 (树状数组 & 线段树)
- URAL - 1989 Subpalindromes hash & 树状数组 | 线段树
- UVA 11990 ”Dynamic“ Inversion(线段树+树状数组)
- 【UVA, 11990】“Dynamic” Inversion【平方分割n】
- POJ 3928 & hdu 2492 & Uva1428 PingPong 【树状数组】
- Hdu1166 敌兵布阵 [分块][树状数组][线段树]
- hdu1166 敌兵布阵(树状数组 && 线段树单点更新)
- CodeChef "Chef and Churus" 分块+树状数组
- Codeforces Round #261 (Div. 2) D. Pashmak and Parmida's problem (树状数组)
- HDU 1934 Minimum Inversion Number(树状数组,线段树)
- POJ 3468(树状数组 && 线段树)
- HDU 1166 敌兵布阵 (线段树基础&树状数组基础)
- hdu 1166 敌兵布阵【入门线段树 & 树状数组】