bzoj 3289 Mato的文件管理(莫队算法+BIT)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3289
【题意】
回答若干个询问:[l,r]区间内的逆序对个数。
【思路】
莫队算法,BIT维护插入删除。
使用BIT维护当前指针l,r内的所有的数。考虑转移部分:
l<q[i].l 删出区间中比a[l]小的数与之构成的逆序对,Q(a[l]-1)
l>q[i].l l++,添加区间中比a[l]小的数与之构成的逆序对,Q(a[l]-1)
r>q[i].r 删除区间中比a[r]大的数与之构成的逆序对,r-l+1-Q(a[r])
r<q[i].r r++,添加区间中比a[r]大的数与之构成的逆序对,r-l-Q(a[r])
相应修改BIT。
这一部分比较容易出错 =_=
【代码】
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #define FOR(a,b,c) for(int a=b;a<=c;a++) 7 using namespace std; 8 9 typedef long long ll; 10 const int N = 1e5+10; 11 12 ll read() { 13 char c=getchar(); 14 ll f=1,x=0; 15 while(!isdigit(c)) { 16 if(c=='-') f=-1; c=getchar(); 17 } 18 while(isdigit(c)) 19 x=x*10+c-'0',c=getchar(); 20 return x*f; 21 } 22 23 struct Node { 24 int pos,id,l,r; 25 bool operator < (const Node& rhs) const 26 { 27 return pos<rhs.pos||(pos==rhs.pos&&r<rhs.r); 28 } 29 } q[N]; 30 31 int n,m; 32 int C[N],a[N],hash[N],tot; 33 ll ans[N]; 34 35 void add(int x,int v) 36 { 37 for(;x<=tot;x+=x&-x) C[x]+=v; 38 } 39 ll query(int x) 40 { 41 ll sum=0; 42 for(;x;x-=x&-x) sum+=(ll)C[x]; 43 return sum; 44 } 45 46 int main() 47 { 48 n=read(); 49 FOR(i,1,n) a[i]=read(),hash[++tot]=a[i]; 50 sort(hash+1,hash+n+1); 51 tot=unique(hash+1,hash+n+1)-hash-1; 52 FOR(i,1,n) a[i]=lower_bound(hash+1,hash+n+1,a[i])-hash; 53 54 m=read(); 55 int B=sqrt(n); 56 FOR(i,1,m) 57 { 58 q[i].l=read(), 59 q[i].r=read(); 60 q[i].id=i; 61 q[i].pos=(q[i].l-1)/B+1; 62 } 63 sort(q+1,q+m+1); 64 65 ll now=0; 66 int l=1,r=0; 67 FOR(i,1,m) 68 { 69 while(l<q[i].l) 70 now-=query(a[l]-1),add(a[l],-1),l++; 71 while(l>q[i].l) 72 l--,now+=query(a[l]-1),add(a[l],1); 73 while(r>q[i].r) 74 now-=r-l+1-query(a[r]),add(a[r],-1),r--; 75 while(r<q[i].r) 76 r++,now+=r-l-query(a[r]),add(a[r],1); 77 ans[q[i].id]=now; 78 } 79 80 FOR(i,1,m) 81 printf("%lld\n",ans[i]); 82 return 0; 83 }
posted on 2016-04-01 14:52 hahalidaxin 阅读(287) 评论(0) 编辑 收藏 举报