bzoj2141: 排队
2016-01-01 01:56
267 查看
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2141
题意:中文题。
分析:先将数组离散化一下,然后对于每一次交换考虑两个元素改变是对逆序对总和的影响就好了,在查找当前值x对逆序对总和影响时分3中情况,第一种是和x在同一个块内的数,sqrt(n)扫一遍即可,第二种是在x所在的块前面的块内,第三种是在x所在的块后面的块内,在块内的个数二分即可,记得在改变的时候要将被改变的那个块重构一下。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=20010; const int MAX=151; const int MOD=1000000007; const int MOD1=100000007; const int MOD2=100000009; const int INF=1000000000; const double EPS=0.00000001; typedef long long ll; typedef unsigned long long ull; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int k,n,clo,ans,f ; int b ,c ,d ; struct node { int u,v; }a ; int cmd(node x,node y) { return x.u<y.u; } void init() { scanf("%d", &n); for (int i=1;i<=n;i++) { scanf("%d", &a[i].u);a[i].v=i; } clo=(int)sqrt(n); k=a[0].u=a[0].v=0; sort(a,a+n+1,cmd); for (int i=1;i<=n;i++) if (a[i].u==a[i-1].u) d[a[i].v]=k; else d[a[i].v]=++k; for (int i=1;i<=n;i++) { b[i]=d[i];c[i]=(i+clo-1)/clo; } for (int i=1;i<=n/clo;i++) sort(b+(i-1)*clo+1,b+i*clo+1); sort(b+n/clo*clo+1,b+n+1); } int get(int x) { int ret=0; for (;x;x-=x&(-x)) ret+=f[x]; return ret; } void add(int x,int y) { for (;x<=k;x+=x&(-x)) f[x]+=y; } void deal() { ans=0;memset(f,0,sizeof(f)); for (int i=1;i<=n;i++) { add(d[i],1);ans+=i-get(d[i]); } printf("%d\n", ans); } int getbig(int i,int x) { int l=(i-1)*clo,r,w,mid; if (i==n/clo+1) { r=n+1;w=n; } else { r=i*clo+1;w=i*clo; } mid=(l+r)/2; while (l+1<r) if (b[mid]<=x) { l=mid;mid=(l+r)/2; } else { r=mid;mid=(l+r)/2; } return w-l; } int getsmall(int i,int x) { int l=(i-1)*clo,r,w,mid; if (i==n/clo+1) { r=n+1;w=l; } else { r=i*clo+1;w=l; } mid=(l+r)/2; while (l+1<r) if (b[mid]<x) { l=mid;mid=(l+r)/2; } else { r=mid;mid=(l+r)/2; } return l-w; } int getn(int x) { int i,l=(c[x]-1)*clo+1,r,ret=0; if (c[x]==n/clo+1) r=n; else r=c[x]*clo; for (i=l;i<x;i++) if (d[i]>d[x]) ret++; for (i=x+1;i<=r;i++) if (d[i]<d[x]) ret++; for (i=1;i<c[x];i++) ret+=getbig(i,d[x]); for (i=c[x]+1;i<=n/clo+1;i++) ret+=getsmall(i,d[x]); return ret; } void change(int x) { int i,l=(x-1)*clo+1,r; if (x==n/clo+1) r=n; else r=x*clo; for (i=l;i<=r;i++) b[i]=d[i]; sort(b+l,b+r+1); } void quiry() { int m,x,y,yx,yy; scanf("%d", &m); while (m--) { scanf("%d%d", &x, &y); if (x>y) swap(x,y); yx=d[x];yy=d[y]; if (yx==yy) printf("%d\n", ans); else { ans-=getn(x);ans-=getn(y); if (d[x]>d[y]) ans++; d[x]=yy;change(c[x]); d[y]=yx;change(c[y]); ans+=getn(x);ans+=getn(y); if (d[x]>d[y]) ans--; printf("%d\n", ans); } } } int main() { init(); deal(); quiry(); return 0; } /* 3 130 150 140 2 2 3 1 3 7 78 976 321 108 3 2 3 10 1 4 2 5 7 3 1 7 3 6 2 1 5 7 1 4 3 6 4 2 */
相关文章推荐
- JTA介绍
- 中国云计算
- 文章标题
- 第九次Scrum meeting
- 今天我来整理下自己开发CM完成第一个项目HTC a5 的编译过程
- nginx的部署与发布
- 魏兴国(云舒):深入浅出DDoS***防御
- 黑马程序员——IO之文件名过滤器
- ios沙盒(sandbox)
- 实现一个函数,可以左旋字符串中的k个字符
- java定时器
- [看书日记20160101]新年第一发,性能优化
- 每瓶汽水1元,两个空瓶可以置换一瓶汽水,现在有20元,最多能喝多少瓶汽水。
- 用git管理源代码
- nginx安装
- 文件下载思路
- android中xml tools属性详解
- ORACLE 重做日志
- 自定义UITabBar的两种方式
- php操作mysql