bzoj2141: 排队
来源:互联网 发布:360全景展示软件 编辑:程序博客网 时间:2024/04/28 20:16
链接: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[N];int b[N],c[N],d[N];struct node { int u,v;}a[N];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;}/*3130 150 14022 31 3778 976 321 108 3 2 3101 42 57 31 73 62 15 71 43 64 2*/
0 0
- bzoj2141: 排队
- bzoj2141: 排队
- bzoj2141: 排队
- bzoj2141排队
- 【bzoj2141】排队
- 【Bzoj2141】排队
- bzoj2141[排队]
- BZOJ2141 排队(分块)
- 【国家集训队2011】【BZOJ2141】排队
- 【bzoj2141】 排队 树状数组+主席树
- 【bzoj2141】【排队】【树状数组套平衡树】
- bzoj2141: 排队(树套树 或 分块)
- [BZOJ2141]排队(分块+树状数组求逆序对)
- bzoj2141【分块+树状数组】
- 排队
- 排队
- 排队
- 排队
- [看书日记20160101]新年第一发,性能优化
- java定时器
- ios沙盒(sandbox)
- 黑马程序员——IO之文件名过滤器
- 今天我来整理下自己开发CM完成第一个项目HTC a5 的编译过程
- bzoj2141: 排队
- 文章标题
- C 语言字符测试函数的用法举例 - 2016.01.01
- MFC 用 Direct2D 显示图像到 Picture Control 中
- druid 数据库密码加密
- 解决linux 命令行乱码
- python实现onvif协议-1
- 记录4种解析xml字符串的方法
- Android AutoLayout全新的适配方式 堪称适配终结者