传送门

题解

听别人说这是洛谷用户的双倍经验啊……然而根本没有感觉到……因为另外的那题我是用树状数组套主席树做的……而且莫名其妙感觉那种方法思路更清晰(虽然码量稍稍大了那么一点点)……感谢Candy大佬教会了我CDQ的动态逆序对……莫名其妙1A了……

因为是删除,所以可以看成倒着加入。而且没规定都在$n$以内,所以要离散。我们把每一个位置都表示成一个三元组$(t,x,y)$,其中$t$表示加入的时间,$x$表示在原数组中的位置,$y$表示离散之后的值。求逆序对,就代表求有多少个三元组满足$t'<t,x'<x,y'>y$或$t'<t,x'>x,y'<y$。我们可以先把时间这一维排序,然后CDQ的时候顺便排好$x$这一维,$y$这一维用树状数组求解。因为要找两种,所以CDQ的时候要两个分别找,这一部分的细节可以参考代码

  1. //minamoto
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #define ll long long
  6. using namespace std;
  7. #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  8. char buf[<<],*p1=buf,*p2=buf;
  9. inline int read(){
  10. #define num ch-'0'
  11. char ch;bool flag=;int res;
  12. while(!isdigit(ch=getc()))
  13. (ch=='-')&&(flag=true);
  14. for(res=num;isdigit(ch=getc());res=res*+num);
  15. (flag)&&(res=-res);
  16. #undef num
  17. return res;
  18. }
  19. char sr[<<],z[];int C=-,Z;
  20. inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
  21. inline void print(ll x){
  22. if(C><<)Ot();if(x<)sr[++C]=,x=-x;
  23. while(z[++Z]=x%+,x/=);
  24. while(sr[++C]=z[Z],--Z);sr[++C]=' ';
  25. }
  26. const int N=4e4+;
  27. int n,m,c[N],ty,yy[N];
  28. inline void add(int x,int val){
  29. for(;x<=ty;x+=x&-x) c[x]+=val;
  30. }
  31. inline int query(int x){
  32. int res=;
  33. for(;x;x-=x&-x) res+=c[x];
  34. return res;
  35. }
  36. inline void clear(int x){
  37. for(;x<=ty;x+=x&-x)
  38. if(c[x]) c[x]=;else break;
  39. }
  40. struct node{
  41. int t,x,y;
  42. node(){}
  43. node(int t,int x,int y):t(t),x(x),y(y){}
  44. bool operator <(const node &b)const
  45. {return x==b.x?y<b.y:x<b.x;}
  46. }a[N],p[N];
  47. inline bool cmptime(const node &a,const node &b){
  48. return a.t==b.t?a.x<b.x:a.t<b.t;
  49. }
  50. ll ans[N];
  51. void CDQ(int l,int r){
  52. if(l==r) return;
  53. int mid=l+r>>;
  54. CDQ(l,mid),CDQ(mid+,r);
  55. for(int i=l,j=l,k=mid+;i<=r;){
  56. if(k>r||(j<=mid&&a[j]<a[k])) add(a[j].y,),p[i++]=a[j++];
  57. else ans[a[k].t]+=query(n)-query(a[k].y),p[i++]=a[k++];
  58. }
  59. for(int i=l;i<=mid;++i) clear(a[i].y);
  60. for(int i=l;i<=r;++i) a[i]=p[i];
  61. for(int i=r;i>=l;--i){
  62. if(a[i].t<=mid) add(a[i].y,);
  63. else ans[a[i].t]+=query(a[i].y-);
  64. }
  65. for(int i=l;i<=r;++i) clear(a[i].y);
  66. }
  67. int main(){
  68. //freopen("testdata.in","r",stdin);
  69. n=read(),m=read();
  70. for(int i=;i<=n;++i){
  71. yy[i]=read(),a[i]=node(,i,yy[i]);
  72. }
  73. sort(yy+,yy++n);
  74. ty=unique(yy+,yy++n)-yy-;
  75. for(int i=;i<=n;++i) a[i].y=lower_bound(yy+,yy++ty,a[i].y)-yy;
  76. int Time=n;
  77. for(int i=;i<=m;++i){
  78. int k=read();a[k].t=Time--;
  79. }
  80. for(int i=;i<=n;++i) if(!a[i].t) a[i].t=Time--;
  81. sort(a+,a++n,cmptime);
  82. CDQ(,n);
  83. for(int i=;i<=n;++i) ans[i]+=ans[i-];
  84. for(int i=n;i>=n-m;--i) print(ans[i]);
  85. Ot();
  86. return ;
  87. }

洛谷P1393 动态逆序对(CDQ分治)的更多相关文章

  1. P3157 动态逆序对 CDQ分治

    动态逆序对 CDQ分治 传送门:https://www.luogu.org/problemnew/show/P3157 题意: 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对 ...

  2. [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...

  3. BZOJ 3295 动态逆序对 | CDQ分治

    BZOJ 3295 动态逆序对 这道题和三维偏序很类似.某个元素加入后产生的贡献 = time更小.pos更小.val更大的元素个数 + time更小.pos更大.val更小的元素个数. 分别用类似C ...

  4. 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治

    [BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...

  5. bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)

    3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...

  6. BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治

    题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 1 ...

  7. 洛谷P3157 动态逆序对 [CQOI2011] cdq分治

    正解:cdq分治 解题报告: 传送门! 长得有点像双倍经验还麻油仔细看先放上来QwQ! 这题首先想到的就直接做逆序对,然后记录每个点的贡献,删去就减掉就好 但是仔细一想会发现布星啊,如果有一对逆序对的 ...

  8. 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治

    题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...

  9. [CQOI2011]动态逆序对 CDQ分治

    洛谷上有2道相同的题目(基本是完全相同的,输入输出格式略有不同) ---题面--- ---题面--- CDQ分治 首先由于删除是很不好处理的,所以我们把删除改为插入,然后输出的时候倒着输出即可 首先这 ...

随机推荐

  1. Linux下的终端快捷键

    今天才发现Linux下的终端有这么多好用的快捷键. Shift+Ctrl+T:新建标签页 Shift+Ctrl+W:关闭标签页 Ctrl+PageUp:前一标签页 Ctrl+PageDown:后一标签 ...

  2. 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】

    题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...

  3. 使screen支持滚动

    在Linux中,常用的串口工具有minicom和screen,minicom可能使用得比较多,但是我比较喜欢screen,因为它的输出是彩色的,更舒服.更能突出重点. 使用screen来打开串口也非常 ...

  4. 最小子串覆盖 · Minimum Window Substring

    [抄题]: 给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串. 在答案的子串中的字母在目标字符串中是否需要具有相同的顺序? ——不需要. ...

  5. android4.2 高用zing拍照后,返回其它页面操作时,主线程关掉或程序退出的问题解决

    产生错误的代码: @Override protected void onCreate(Bundle savedInstanceState) { StrictMode.setThreadPolicy(n ...

  6. Shell脚本传递带有空格的参数[摘录自网络]

    参数处理 说明 $# 传递到脚本的参数个数 $* 以一个单字符串显示所有向脚本传递的参数 $$ 脚本运行的当前进程ID号 $! 后台运行的最后一个进程的ID号 $@ 与$#相同,但是使用时加引号,并在 ...

  7. 看图说说Sun HotSpot虚拟机对象

  8. Hdu1547 Bubble Shooter 2017-01-20 18:38 44人阅读 评论(0) 收藏

    Bubble Shooter Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Tota ...

  9. 23 DesignPatterns学习笔记:C++语言实现

    DesignPatterns学习笔记:C++语言实现 (转载请注明出处:http://www.cnblogs.com/icmzn/p/5680784.html) 1. 创建型设计模式: (1)Faco ...

  10. Android-无序广播

    在之前的博客,Android-广播概念,中介绍了(广播和广播接收者)可以组件与组件之间进行通讯,有两种类型的广播(无序广播 和 有序广播),这篇博客就来讲解无序广播的代码实现: 无序广播:接收者 同时 ...