终于有时间写博客了,前面一直咕咕咕都快变成一只公鸡了......这次考试,真的很意外,我在考场上觉得自己打出了T1的正解,样例一拍就过,还跑得嘎嘎快,然后T2,T3码了两个暴力,觉得自己应该能100pts+,结果竟然....爆蛋了,T1思路出现了问题,T2打假了,T3TLE飞起,但是收获还是有的,以后注意多加思考,看看自己的思路有没有正确性,还有,一定要用暴力程序进行验证(暴力不要打假...),样例真是太水了....

T1 Game

思路:最大得分可以利用线段树很容易求出,如果没有字典序最大的限制,那么这道题就非常简单,但这只是如果,现在这道题有了双重限制,听某巨佬的叙述,得知一般有双重限制的题一般有两种思考方向,一种是二分,另一种是主席树,那么很显然,这道题我们可以考虑二分的思想,具体来说就是我们先通过线段树求出最大得分,然后考虑这样一件事情,如果有一对点可以对答案造成贡献,那么我们将他们同时删去必然会使更新后的最大得分-1,这样我们就可以进行二分查找了,对于可以造成贡献的点,我们二分出他可以对应的最大的另外一个点,具体实现见代码:

AC_code

  1. #include<bits/stdc++.h>
  2. #define re register int
  3. #define ii inline int
  4. #define iv inline void
  5. #define lc (rt<<1)
  6. #define rc (rt<<1|1)
  7. using namespace std;
  8. const int N=200010;
  9. const int INF=1e9+10;
  10. int n;
  11. int a[N],b[N];
  12. multiset<int> sm;
  13. ii read()
  14. {
  15. int x=0;
  16. bool f=1;
  17. char ch=getchar();
  18. while(ch<'0'||ch>'9')
  19. {
  20. if(ch=='-')
  21. f=0;
  22. ch=getchar();
  23. }
  24. while(ch>='0'&&ch<='9')
  25. {
  26. x=(x<<1)+(x<<3)+(ch^48);
  27. ch=getchar();
  28. }
  29. return f?x:(-x);
  30. }
  31. struct Segment_Tree
  32. {
  33. int A[N<<2],B[N<<2],sum[N<<2];
  34. iv pp(int rt)
  35. {
  36. int u=min(A[lc],B[rc]);
  37. sum[rt]=sum[lc]+sum[rc]+u;
  38. A[rt]=A[lc]+A[rc]-u;
  39. B[rt]=B[lc]+B[rc]-u;
  40. }
  41. iv insert(int rt,int l,int r,int p,int x,int y)
  42. {
  43. if(l==r)
  44. {
  45. A[rt]+=x;
  46. B[rt]+=y;
  47. return;
  48. }
  49. int mid=(l+r)>>1;
  50. if(mid>=p)
  51. insert(lc,l,mid,p,x,y);
  52. else
  53. insert(rc,mid+1,r,p,x,y);
  54. pp(rt);
  55. }
  56. }T;
  57. int main()
  58. {
  59. const int N=100000;
  60. n=read();
  61. for(re i=1;i<=n;i++)
  62. {
  63. a[i]=read();
  64. T.insert(1,1,N,a[i],1,0);
  65. }
  66. for(re i=1;i<=n;i++)
  67. {
  68. b[i]=read();
  69. T.insert(1,1,N,b[i],0,1);
  70. sm.insert(b[i]);
  71. }
  72. int ans=T.sum[1];
  73. for(re i=1;i<=n;i++)
  74. {
  75. int l=a[i]+1,r=*(--sm.end()),out=-1;
  76. T.insert(1,1,N,a[i],-1,0);
  77. while(l<=r)
  78. {
  79. int mid=(l+r)>>1;
  80. T.insert(1,1,N,mid,0,-1);
  81. if(T.sum[1]+1==ans)
  82. {
  83. l=mid+1;
  84. out=mid;
  85. }
  86. else
  87. r=mid-1;
  88. T.insert(1,1,N,mid,0,1);
  89. }
  90. if(out!=-1)
  91. {
  92. --ans;
  93. sm.erase(sm.find(out));
  94. T.insert(1,1,N,out,0,-1);
  95. printf("%d ",out);
  96. }
  97. else
  98. {
  99. l=1,r=a[i],out;
  100. while(l<=r)
  101. {
  102. int mid=(l+r)>>1;
  103. T.insert(1,1,N,mid,0,-1);
  104. if(T.sum[1]==ans)
  105. {
  106. l=mid+1;
  107. out=mid;
  108. }
  109. else
  110. r=mid-1;
  111. T.insert(1,1,N,mid,0,1);
  112. }
  113. printf("%d ",out);
  114. sm.erase(sm.find(out));
  115. T.insert(1,1,N,out,0,-1);
  116. }
  117. }
  118. return 0;
  119. }


T2 Time

这道题,或者说是这一种对数列进行排列的题,我是比较不自信的,因为自己不怎么有思路,导致我没有留出时间进行思考,这也是一个教训,逃避不是永久的办法,只有自己敢去想,去做,才能解决问题。

思路:这道题要求小的数字往两边靠,那很显然,如果要做到最小操作次数就要比较向左还是向右移动更优,可以利用线段树或者树状数组实现,算法的正确性在于,当我们将小数字向边缘移动的时候,我们都会将比他大的数字向中心移动,所以我们只需要利用贪心的思想只考虑使当前最优即可。

AC_code


  1. #include<bits/stdc++.h>
  2. #define re register int
  3. #define ii inline int
  4. #define iv inline void
  5. #define lc (rt<<1)
  6. #define rc (rt<<1|1)
  7. #define mid ((l+r)>>1)
  8. using namespace std;
  9. const int N=1e5+10;
  10. const int INF=1e9+10;
  11. int n;
  12. deque<int>q[N];
  13. ii read()
  14. {
  15. int x=0;
  16. bool f=1;
  17. char ch=getchar();
  18. while(ch<'0'||ch>'9')
  19. {
  20. if(ch=='-')
  21. f=0;
  22. ch=getchar();
  23. }
  24. while(ch>='0'&&ch<='9')
  25. {
  26. x=(x<<1)+(x<<3)+(ch^48);
  27. ch=getchar();
  28. }
  29. return f?x:(-x);
  30. }
  31. struct Segment_Tree
  32. {
  33. int sum[N<<2];
  34. iv pp(int rt)
  35. {
  36. sum[rt]=sum[lc]+sum[rc];
  37. }
  38. iv insert(int rt,int l,int r,int p,int z)
  39. {
  40. if(l==r)
  41. {
  42. sum[rt]+=z;
  43. return;
  44. }
  45. if(mid>=p)
  46. insert(lc,l,mid,p,z);
  47. else
  48. insert(rc,mid+1,r,p,z);
  49. pp(rt);
  50. }
  51. ii query(int rt,int l,int r,int L,int R)
  52. {
  53. if(L>R)
  54. return 0;
  55. if(L<=l&&r<=R)
  56. return sum[rt];
  57. if(mid>=R)
  58. return query(lc,l,mid,L,R);
  59. if(mid<L)
  60. return query(rc,mid+1,r,L,R);
  61. return query(lc,l,mid,L,R)+query(rc,mid+1,r,L,R);
  62. }
  63. }T;
  64. int main()
  65. {
  66. int ans=0;
  67. n=read();
  68. for(re i=1;i<=n;i++)
  69. {
  70. q[read()].push_back(i);
  71. T.insert(1,1,n,i,1);
  72. }
  73. for(re i=1;i<=n;i++)
  74. {
  75. while(!q[i].empty())
  76. {
  77. int l=q[i].front(),r=q[i].back();
  78. int sl=T.query(1,1,n,1,l-1),sr=T.query(1,1,n,1,n)-T.query(1,1,n,1,r);
  79. if(sl<=sr)
  80. {
  81. ans+=sl;
  82. T.insert(1,1,n,l,-1);
  83. q[i].pop_front();
  84. }
  85. else
  86. {
  87. ans+=sr;
  88. T.insert(1,1,n,r,-1);
  89. q[i].pop_back();
  90. }
  91. }
  92. }
  93. printf("%d\n",ans);
  94. return 0;
  95. }


T3 Cover

好吧,这道题怪我没有认真听课,区间两两之间只有包含和不相交的关系满足这个条件,他们的包含关系一定会构成一颗树,那么这道题显然就是一个树形DP(而不是我写的区间DP),记 \(f_{i,j}\)表示在 i 为根的子树中点被覆盖的最多次数为 j 的最优答案,转移

的时候首先将所有子树的答案直接合并,然后考虑点 i 的贡献 \(f_{i,j}=max(f_{i,j},f_{i,j-1}+val)\) , 这样朴素的DP方程显然时间复杂度会爆炸,考虑优化,我们考虑答案更新的过程,我们利用包含关系构建一颗树,那么我们将子树合并的时候,当前的节点会存储多个val,包括自己本身的,还有自己的儿子合并得到的,这种答案属于同一层,我们需要不同层之间的转移。也就是到达跟节点的时候我们需要不断从左右区间中分别拿出最大值,这就是我们需要的答案,那么我们就可以利用一个 set ,通过一个合并的操作插入值并排序,具体实现见代码:

AC_code

  1. #include<bits/stdc++.h>
  2. #define re register int
  3. #define ii inline int
  4. #define iv inline void
  5. #define lc (rt<<1)
  6. #define rc (rt<<1|1)
  7. #define mid ((l+r)>>1)
  8. using namespace std;
  9. const int N=1e5+10;
  10. const int INF=1e9+10;
  11. int n;
  12. deque<int>q[N];
  13. ii read()
  14. {
  15. int x=0;
  16. bool f=1;
  17. char ch=getchar();
  18. while(ch<'0'||ch>'9')
  19. {
  20. if(ch=='-')
  21. f=0;
  22. ch=getchar();
  23. }
  24. while(ch>='0'&&ch<='9')
  25. {
  26. x=(x<<1)+(x<<3)+(ch^48);
  27. ch=getchar();
  28. }
  29. return f?x:(-x);
  30. }
  31. struct Segment_Tree
  32. {
  33. int sum[N<<2];
  34. iv pp(int rt)
  35. {
  36. sum[rt]=sum[lc]+sum[rc];
  37. }
  38. iv insert(int rt,int l,int r,int p,int z)
  39. {
  40. if(l==r)
  41. {
  42. sum[rt]+=z;
  43. return;
  44. }
  45. if(mid>=p)
  46. insert(lc,l,mid,p,z);
  47. else
  48. insert(rc,mid+1,r,p,z);
  49. pp(rt);
  50. }
  51. ii query(int rt,int l,int r,int L,int R)
  52. {
  53. if(L>R)
  54. return 0;
  55. if(L<=l&&r<=R)
  56. return sum[rt];
  57. if(mid>=R)
  58. return query(lc,l,mid,L,R);
  59. if(mid<L)
  60. return query(rc,mid+1,r,L,R);
  61. return query(lc,l,mid,L,R)+query(rc,mid+1,r,L,R);
  62. }
  63. }T;
  64. int main()
  65. {
  66. int ans=0;
  67. n=read();
  68. for(re i=1;i<=n;i++)
  69. {
  70. q[read()].push_back(i);
  71. T.insert(1,1,n,i,1);
  72. }
  73. for(re i=1;i<=n;i++)
  74. {
  75. while(!q[i].empty())
  76. {
  77. int l=q[i].front(),r=q[i].back();
  78. int sl=T.query(1,1,n,1,l-1),sr=T.query(1,1,n,1,n)-T.query(1,1,n,1,r);
  79. if(sl<=sr)
  80. {
  81. ans+=sl;
  82. T.insert(1,1,n,l,-1);
  83. q[i].pop_front();
  84. }
  85. else
  86. {
  87. ans+=sr;
  88. T.insert(1,1,n,r,-1);
  89. q[i].pop_back();
  90. }
  91. }
  92. }
  93. printf("%d\n",ans);
  94. return 0;
  95. }


noip模拟测试31的更多相关文章

  1. [NOIP模拟测试31]题解

    A.math 考场乱搞拿了95,2333. 考虑裴蜀定理:$ax+by=z$存在整数解,当且仅当$gcd(a,b)|z$. 那么如果某个数能够被拼出来,就必须满足所有$a_i$的$gcd$是它的因子. ...

  2. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  3. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  4. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  5. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  6. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

  7. 「题解」NOIP模拟测试题解乱写I(29-31)

    NOIP模拟29(B) T1爬山 简单题,赛时找到了$O(1)$查询的规律于是切了. 从倍增LCA那里借鉴了一点东西:先将a.b抬到同一高度,然后再一起往上爬.所用的步数$×2$就是了. 抬升到同一高 ...

  8. NOIP模拟测试1(2017081501)

    好,今天是cgg第一次举行模拟测试,希望各位支持. 时间限制:2小时 题目链接: 题目一:水得都没名字了 题目二:车站 题目三:选数 不要觉得2小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...

  9. 2019.8.14 NOIP模拟测试21 反思总结

    模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...

随机推荐

  1. Pytorch项目基本结构

    梳理一下Pytorch项目的基本结构(其实TF的也差不多是这样,这种思路可以迁移到别的深度学习框架中) 结构树 -------checkpoints #存放训练完成的模型文件 ​ ----xxx.pk ...

  2. .NET Core/.NET5/.NET6 开源项目汇总9:客户端跨平台UI框架

    系列目录     [已更新最新开发文章,点击查看详细] .NET Core 实现了跨平台,支持在 Windwos.Linux.macOS上开发与部署,但是也仅限于Web应用程序.对于Windows桌面 ...

  3. CS 面试题目总结(问题+答案)

    开源了一个新的github仓库CS 面试题目总结(问题+答案),主要总结一些CS大厂常见的面试问题,所有的问题与答案参考了网络上的许多博客和github仓库,也希望各位读者能够对这个仓库进行补充,毕竟 ...

  4. 基于HSI和局部同态滤波的彩色图像增强

    简介 在图像采集过程中,由于光照环境或物体表面反光等原因会造成图像光照不均 .图像的光照不均会直接影响图像分析的结果.因此,对光照不均图像进行增强,消除光照的影响是光照不均图像处理中不可缺少的环节 . ...

  5. oracle :如何测试数据库安装是否成功

    要测试数据安装是否成功,可按顺序执行以下两个步骤: 测试步骤 1:  请执行操作系统级的命令: tnsping orcl (如果出现[TNS-03505:无法解析名称]的提示错误: 那就改为tnspi ...

  6. css文字动画(自动换文字)

    html: <div class="content"> <div class="content__container"> <p c ...

  7. 如何Spring Cloud Zuul作为网关的分布式系统中整合Swagger文档在同一个页面上

    本文不涉及技术,只是单纯的一个小技巧. 阅读本文前,你需要对spring-cloud-zuul.spring-cloud-eureka.以及swagger的配置和使用有所了解. 如果你的系统也是用zu ...

  8. Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?

    Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题? Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解 ...

  9. 【知识点】H264, H265硬件编解码基础及码流分析

    前言 音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps,pps,vps,start code以及基本的工作原理,而大 ...

  10. Mybatis代码自动生成(含测试)

    一.建立数据库 create database shixun; use shixun; create table user( id int primary key auto_increment , u ...