【BZOJ2141】排队

这道题和动态逆序对比较像(BZOJ-3295 没做过的同学建议先做这题),只是删除操作变成了交换。解法:交换操作可以变成删除加插入操作,那么这题就变成了 (时间,位置,值)的三维偏序问题,考虑用CDQ分治解决:时间排序,位置分治,值树状数组。

但是这里要特别注意的是:本题因为有多个插入删除操作,所以多能会有多个操作的位置是相同的,但是逆序对要求的是位置比它小/大,值比它大/小的对,就是位置相等的不能算贡献。所以我们对CDQ分治的第二维的归并顺序就有讲究:必须是位置严格小于才放到左边然后插入树状数组,也就是说左边位置必须严格小于右边位置才算贡献。

其实这样说也不太对,(蒟蒻开始口胡)应该说CDQ分治的本质是:对于一个询问,它的答案就是所有比它早的修改对这个询问产生的影响累加的结果。也就是说其实分治的顺序并不是十分重要,只要达到了上面这个目标即可,但是往往我们为了方便统计答案会修改分治顺序使得这样做利于统计答案。举个例子就是像这题哪怕把分治顺序改为return x<rhs.x || x==rhs.x && z<rhs.z;只要把统计答案改为Q[p].x<Q[q].x其实也是OK的,只不过会使得分治和统计答案分开了而已。

细节见代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+;
int n,m,qid,a[N],b[N],ans[N];
struct rec{
int x,y,z,aid; //位置,插入/删除,值,答案下标
bool operator < (const rec &rhs) const {
return x<rhs.x;
}
}Q[N],tmp[N]; int sum[N];
void update(int x,int v) {
for (;x<=n;x+=x&-x) sum[x]+=v;
}
int query(int x) {
int ret=;
for (;x;x-=x&-x) ret+=sum[x];
return ret;
} void CDQ(int l,int r) {
if (l>=r) return;
int mid=l+r>>;
CDQ(l,mid); CDQ(mid+,r);
int p=l,q=mid+,o=l-;
while (p<=mid || q<=r) //归并排序结果
if (q>r || p<=mid && Q[p]<Q[q]) tmp[++o]=Q[p++]; else tmp[++o]=Q[q++]; p=l; q=mid+;
while (p<=mid || q<=r) //正向算逆序对
if (q>r || p<=mid && Q[p]<Q[q]) update(Q[p].z,Q[p].y),p++;
else ans[Q[q].aid]+=Q[q].y*(query(n)-query(Q[q].z)),q++;
for (int i=l;i<=mid;i++) update(Q[i].z,-Q[i].y); p=mid; q=r;
while (p>=l || q>mid) //反向算逆序对
if (q<=mid || p>=l && Q[q]<Q[p]) update(Q[p].z,Q[p].y),p--;
else ans[Q[q].aid]+=Q[q].y*(query(Q[q].z-)),q--;
for (int i=l;i<=mid;i++) update(Q[i].z,-Q[i].y); for (int i=l;i<=r;i++) Q[i]=tmp[i];
} int main()
{
cin>>n;
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+);
int t=unique(b+,b+n+)-(b+);
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b+t+,a[i])-b;
for (int i=;i<=n;i++) Q[++qid]=(rec){i,,a[i],}; cin>>m;
for (int i=;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
Q[++qid]=(rec){x,-,a[x],i};
Q[++qid]=(rec){x,,a[y],i};
Q[++qid]=(rec){y,-,a[y],i};
Q[++qid]=(rec){y,,a[x],i};
swap(a[x],a[y]);
} CDQ(,qid);
for (int i=;i<=m;i++) {
if (i) ans[i]+=ans[i-];
printf("%d\n",ans[i]);
}
return ;
}

最新文章

  1. Google和Baidu常用的搜索技巧--转
  2. 安装了简易版XP系统后不能安装IIS的解决办法
  3. IOS主要框架介绍(转)
  4. ecshop适应PHP7的修改
  5. Servlet的request应用案例
  6. CISA 信息系统审计知识点 [第二章. IT治理和管理 ]
  7. vs vim 插件
  8. linux下c++實現簡單的生產者消費者隊列模式
  9. 【原创】setjmp longjump一些注意点及使用方法
  10. hdu4081 次小生成树变形
  11. leetcode第六题 ZigZag Conversion (java)
  12. How to append files to a .tar archive using Apache Commons Compress?(转)
  13. 重登陆模式 --ESFramework 4.0 快速上手(07)
  14. 关于O(logN)的正确理解
  15. nyoj 聪明的kk
  16. c++ 深入理解数组
  17. 奇yin技巧
  18. MQTT
  19. OpenJS Foundation
  20. 洛谷 P1378 油滴扩展 改错

热门文章

  1. Git关联JIRA的issue
  2. linux下caffe的命令运行脚本
  3. 使用getchar和putchar输入输出单个字符
  4. hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化
  5. [hadoop](2) MapReducer:Distributed Cache
  6. HashMap 重新学习
  7. 【面经分享】前端小白半年准备,成功进入bat
  8. python中时间戳,datetime 和时间字符串之间得转换
  9. 2019牛客暑期多校训练营(第六场)C - Palindrome Mouse (回文自动机)
  10. Oracle_管理控制文件和日志文件