此题最早看到是在我还什么都不会的去年的暑期集训,是V8讲的DP专题,我当时还跑去问这概率怎么做。这道题要求的是二维最长不上升子序列,加上位置一维就成了三维偏序问题,也就是套用CDQ分治,对位置排序,然后对一维分治,对剩下的一维树状数组,类似的问题用树状数组套平衡树也能解决,但似乎常数很大。然后这题的第一个关键就是在做CDQ的时候先做CDQ(l,mid)的区间,然后去计算左边对右边的影响,最后去计算CDQ(mid+1,r),昨晚看别人博客中说这是显然的,当时我就懵逼了,于是这题今天上课看了很久。发现的确要这么做的,因为其实你是在维护第三维树状数组的时候去做了这个DP的过程,当计算以该点为结尾的最长不上升子序列时,你当然应该先做左区间,然后就可以去更新一下相对右边这些点的值,然后就再去做CDQ的右区间。具体是分别维护区间的最长不上升子序列的长度,以及出现的次数。做法是这样的,首先对左右两边分别按照第二维从小到大排序,将左边的所有的第二维大于右边的点全部加入树状数组,更新第三维,要注意更新和查询的方向正好是反过来的,因为你要查的是大于右边某个值的最长不上升子序列的长度,然后更新一下dp数组,也就是代码中的f[0]数组。然后再把整个序列反过来做一遍CDQ,求以某个点为开始的最长不上升子序列。

加一个学习的链接:https://www.cnblogs.com/liu-runda/p/6416195.html

  1. #include<bits/stdc++.h>
  2. #define ll long double
  3. #define pb push_back
  4. #define _mp make_pair
  5. const int maxn=1e5+7;
  6. const int mod=1e9+7;
  7. using namespace std;
  8. int n;
  9. int h[2][maxn],v[2][maxn];
  10. int iq[maxn],hq[maxn],vq[maxn];
  11. int f[2][maxn];
  12. ll g[2][maxn];
  13. int MAX[maxn];
  14. ll CNT[maxn];
  15. void add1(int x,int w,ll cnt)
  16. {
  17. while(x>0)
  18. {
  19. if(MAX[x]<w)
  20. {
  21. MAX[x]=w;CNT[x]=cnt;
  22. }
  23. else if(MAX[x]==w)CNT[x]+=cnt;
  24. x-=x&-x;
  25. }
  26. }
  27. void add2(int x,int w,ll cnt)
  28. {
  29. while(x<maxn)
  30. {
  31. if(MAX[x]<w)
  32. {
  33. MAX[x]=w;CNT[x]=cnt;
  34. }
  35. else if(MAX[x]==w)CNT[x]+=cnt;
  36. x+=x&-x;
  37. }
  38. }
  39. int query1(int x)
  40. {
  41. int ans=0;
  42. while(x<maxn)
  43. {
  44. if(MAX[x]>ans)ans=MAX[x];
  45. x+=x&-x;
  46. }
  47. return ans;
  48. }
  49. int query2(int x)
  50. {
  51. int ans=0;
  52. while(x>0)
  53. {
  54. if(MAX[x]>ans)ans=MAX[x];
  55. x-=x&-x;
  56. }
  57. return ans;
  58. }
  59. ll query_cnt(int x,int val)
  60. {
  61. ll ans=0;
  62. while(x<maxn)
  63. {
  64. if(MAX[x]==val)ans+=CNT[x];
  65. x+=x&-x;
  66. }
  67. return ans;
  68. }
  69. ll query_cnt2(int x,int val)
  70. {
  71. ll ans=0;
  72. while(x>0)
  73. {
  74. if(MAX[x]==val)ans+=CNT[x];
  75. x-=x&-x;
  76. }
  77. return ans;
  78. }
  79. bool cmp1(const int& a,const int& b)
  80. {
  81. return h[0][a]<h[0][b];
  82. }
  83. bool cmp2(const int& a,const int& b)
  84. {
  85. return v[0][a]<v[0][b];
  86. }
  87. bool cmp3(const int& a,const int& b)
  88. {
  89. return h[1][a]<h[1][b];
  90. }
  91. void del1(int x)
  92. {
  93. while(x>0)
  94. {
  95. MAX[x]=CNT[x]=0;
  96. x-=x&-x;
  97. }
  98. }
  99. void del2(int x)
  100. {
  101. while(x<maxn)
  102. {
  103. MAX[x]=CNT[x]=0;
  104. x+=x&-x;
  105. }
  106. }
  107. void cdq1(int l,int r)
  108. {
  109. if(l==r)return;
  110. int mid=(l+r)>>1;
  111. cdq1(l,mid);
  112. for(int i=l;i<=r;i++)iq[i]=i;
  113. sort(iq+l,iq+mid+1,cmp1);
  114. sort(iq+mid+1,iq+r+1,cmp1);
  115. int pp=mid;
  116. for(int i=r;i>mid;i--)
  117. {
  118. while(pp>=l&&h[0][iq[pp]]>=h[0][iq[i]])
  119. {
  120. add1(v[0][iq[pp]],f[0][iq[pp]],g[0][iq[pp]]);
  121. pp--;
  122. }
  123. int tmp=query1(v[0][iq[i]]);
  124. if(tmp+1>f[0][iq[i]])
  125. {
  126. f[0][iq[i]]=tmp+1;g[0][iq[i]]=query_cnt(v[0][iq[i]],tmp);
  127. }
  128. else if(tmp+1==f[0][iq[i]])
  129. {
  130. g[0][iq[i]]+=query_cnt(v[0][iq[i]],tmp);
  131. }
  132. }
  133. for(int i=mid;i>pp;i--)
  134. {
  135. del1(v[0][iq[i]]);
  136. }
  137. cdq1(mid+1,r);
  138. }
  139. void cdq2(int l,int r)
  140. {
  141. if(l==r)return;
  142. int mid=(l+r)>>1;
  143. cdq2(l,mid);
  144. for(int i=l;i<=r;i++)iq[i]=i;
  145. sort(iq+l,iq+mid+1,cmp3);
  146. sort(iq+mid+1,iq+r+1,cmp3);
  147. int pp=l;
  148. for(int i=mid+1;i<=r;i++)
  149. {
  150. while(pp<=mid&&h[1][iq[pp]]<=h[1][iq[i]])
  151. {
  152. add2(v[1][iq[pp]],f[1][iq[pp]],g[1][iq[pp]]);
  153. pp++;
  154. }
  155. int tmp=query2(v[1][iq[i]]);
  156. if(tmp+1>f[1][iq[i]])
  157. {
  158. f[1][iq[i]]=tmp+1;g[1][iq[i]]=query_cnt2(v[1][iq[i]],tmp);
  159. }
  160. else if(tmp+1==f[1][iq[i]])
  161. {
  162. g[1][iq[i]]+=query_cnt2(v[1][iq[i]],tmp);
  163. }
  164. }
  165. for(int i=l;i<pp;i++)
  166. {
  167. del2(v[1][iq[i]]);
  168. }
  169. cdq2(mid+1,r);
  170. }
  171. int main()
  172. {
  173. scanf("%d",&n);
  174. for(int i=1;i<=n;i++)
  175. {
  176. scanf("%d%d",&h[0][i],&v[0][i]);
  177. iq[i]=i;
  178. }
  179. // cout<<222<<endl;
  180. sort(iq+1,iq+1+n,cmp1);
  181. int tot=0,las=-1;
  182. for(int i=1;i<=n;i++)
  183. {
  184. if(las!=h[0][iq[i]])
  185. {
  186. las=h[0][iq[i]];
  187. ++tot;
  188. }
  189. h[0][iq[i]]=tot;
  190. }
  191. tot=0;las=-1;
  192. for(int i=1;i<=n;i++) iq[i]=i;
  193. sort(iq+1,iq+1+n,cmp2);
  194. for(int i=1;i<=n;i++)
  195. {
  196. if(las!=v[0][iq[i]])
  197. {
  198. las=v[0][iq[i]];
  199. ++tot;
  200. }v[0][iq[i]]=tot;
  201. }
  202. for(int i=1;i<=n;i++)
  203. {
  204. h[1][i]=h[0][n+1-i];
  205. v[1][i]=v[0][n+1-i];
  206. }
  207. for(int i=1;i<=n;i++)
  208. {
  209. iq[i]=i;
  210. f[0][i]=f[1][i]=g[0][i]=g[1][i]=1;
  211. }
  212. // cout<<222<<endl;
  213. cdq1(1,n);cdq2(1,n);
  214. // cout<<222<<endl;
  215. int ans=0;
  216. for(int i=1;i<=n;i++)
  217. {
  218. if(f[0][i]>ans)ans=f[0][i];
  219. }
  220. printf("%d\n",ans);
  221. ll sum=0;
  222. for(int i=1;i<=n;i++)
  223. {
  224. if(f[0][i]==ans)sum+=g[0][i];
  225. }
  226. //cout<<sum<<endl;
  227. for(int i=1;i<=n;i++)
  228. {
  229. // cout<<g[0][i]<<" "<<g[1][n-i+1]<<endl;
  230. if(f[0][i]+f[1][n-i+1]!=ans+1)printf("%.8f ",0.0);
  231. else printf("%.8f ",double(g[0][i]*g[1][n-i+1]/(sum)));
  232. //cout<<endl;
  233. // cout<<222<<endl;
  234. }
  235. // }
  236. // for(int i=1;i<=n;i++) cout<<g[0][i]<<" "<<g[1][n-i+1]<<endl;
  237.  
  238. }

  

BZOJ2244 拦截导弹的更多相关文章

  1. [BZOJ2244]:拦截导弹(DP+CDQ分治+树状数组)

    题目传送门 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于 ...

  2. 【BZOJ2244】[SDOI2011]拦截导弹(CDQ分治)

    [BZOJ2244][SDOI2011]拦截导弹(CDQ分治) 题面 BZOJ 洛谷 题解 不难发现这就是一个三维偏序+\(LIS\)这样一个\(dp\). 那么第一问很好求,直接\(CDQ\)分治之 ...

  3. [BZOJ2244][SDOI2011]拦截导弹 CDQ分治

    2244: [SDOI2011]拦截导弹 Time Limit: 30 Sec  Memory Limit: 512 MB  Special Judge Description 某国为了防御敌国的导弹 ...

  4. BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】

    题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...

  5. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...

  6. codevs1409 拦截导弹2

    [问题描述]一场战争正在 A 国与 B 国之间如火如荼的展开.B 国凭借其强大的经济实力开发出了无数的远程攻击导弹,B 国的领导人希望,通过这些导弹直接毁灭 A 国的指挥部,从而取得战斗的胜利!当然, ...

  7. nyoj814_又见拦截导弹_DP

    又见拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦 ...

  8. 【动态规划】拦截导弹_dilworth定理_最长递增子序列

    问题 K: [动态规划]拦截导弹 时间限制: 1 Sec  内存限制: 256 MB提交: 39  解决: 10[提交][状态][讨论版] 题目描述 张琪曼:“老师,修罗场是什么?” 墨老师:“修罗是 ...

  9. ACM题目————又见拦截导弹

    描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:它的第一发炮弹能够到达任意的高度,但是以后每一发炮 ...

随机推荐

  1. PHP单元测试PHPUnit

    配置说明 1.全局安装phpunit命令脚本 1 2 3 4 5 $ wget https://phar.phpunit.de/phpunit-7.0.phar $ chmod +x phpunit- ...

  2. [转帖]Oracle 裁员史:技术人死于重组,卒于云计算

    Oracle 裁员史:技术人死于重组,卒于云计算 https://www.infoq.cn/article/tm-mcdHCPCI4eEwr6dbY 大厂裁员 我妈妈也总担心我没工作了 怎么还房贷 田 ...

  3. iphone 分辨率相关

    iPhone 1G 320x480 iPhone 3G 320x480 iPhone 3GS 320x480 iPhone 4 640x960 iPhone 4S 640x960 iPhone 5 6 ...

  4. macbookpro 以及 surface 的技术规格

    macbookpro 13.3 英寸 (对角线) LED 背光显示屏 (采用 IPS 技术):初始分辨率 x ( ppi),支持数百万色彩 15.4 英寸 (对角线) LED 背光显示屏 (采用 IP ...

  5. Eclipse在写java时的BUG

    要把这个关掉

  6. VMWARE中NAT下获取不到IP

    1.编辑-虚拟网络编辑器-dhcp设置 2.虚拟机-可移动设备-网络适配器-设置,注意:这里一定要选nat,当初我就是选了桥接,死活上不去,搞了2个小时.

  7. 【转】解决Maxwell发送Kafka消息数据倾斜问题

    最近用Maxwell解析MySQL的Binlog,发送到Kafka进行处理,测试的时候发现一个问题,就是Kafka的Offset严重倾斜,三个partition,其中一个的offset已经快200万了 ...

  8. 排查 Maxwell can not find database 并且使用 MySQL binlog 解决相关问题

    目前我们在使用 Maxwell 在读线上机器的 binlog 同步我们的离线数据库. 这次错误定位上,首先线要确定问题是发生在生产者 还是队列 还是消费者.经过查看各机器上任务的运行日志,定位到了问题 ...

  9. python3高级编程

    1. SMTP发送邮件 internet相关协议: http:网页访问相关,httplib,urllib,xmlrpclib ftp:文件传输相关, ftplib, urllib nntp:新闻和帖子 ...

  10. 01.javascript之数据类型

    1.数据类型 JavaScript一共有六种数据类型.(ES6新增了第七种Symbol类型的值) 数值(Number) 字符串(String) 布尔值(boolean) undefined null ...