NOIP2017提高组模拟赛5 (总结)##

第一题 最远

  1. 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K (2 <= K <= 50,000)小街, 每条小街的尽头有一间房子(小街的其它位置没有房子).每条小街在主线大街的P_i 处分支,(0 <= P_i <= N) , 小街的长度是 L_i (1 <= L_i <= 1,000,000).FJ想知道最远的两个房子之间的距离是多少。

  其实就是将一个点F拆成向左L向右R的两个点,然后将所有点排序(不用排序也行,直接找),①选第一个L,从后往前选第一个不与L同一个F的R。②选最后一个R,从前往后选第一个不与R同一个F的L。①②答案中的最大值即为两点之间的最远距离。

证明如下:

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #define imax(a,b) ((a>b)?(a):(b))
  5. typedef long long ll;
  6. using namespace std;
  7. const int N=120000;
  8. int n,k,dt,ans;
  9. struct data{ int ti,wi; } d[N];
  10. void add(int len,int we) { d[++dt].ti=len; d[dt].wi=we; }
  11. bool cmp(data A,data B) { return (A.ti<B.ti); }
  12. int main()
  13. {
  14. freopen("a.in","r",stdin);
  15. freopen("a.out","w",stdout);
  16. scanf("%d%d",&n,&k);
  17. dt=0; ans=0;
  18. for(int i=1;i<=k;i++)
  19. {
  20. int a,b; scanf("%d%d",&a,&b);
  21. add(a+b,i); add(a-b,i);
  22. }
  23. sort(d+1,d+1+dt,cmp);
  24. for(int i=dt;i>1;i--)
  25. if(d[i].wi!=d[1].wi)
  26. {
  27. ans=imax(ans,d[i].ti-d[1].ti);
  28. break;
  29. }
  30. for(int i=1;i<dt;i++)
  31. if(d[i].wi!=d[dt].wi)
  32. {
  33. ans=imax(ans,d[dt].ti-d[i].ti);
  34. break;
  35. }
  36. printf("%d\n",ans);
  37. return 0;
  38. }

第二题 01游戏

  1. 有一种游戏, 刚开始有A0B1. 你的目标是最后变成A+B1. 每一次,你选中任意K个数字, 把他们的值取反(原来是0的变1, 原来是1的变0).请问至少需要多少次才能达到目标?假如不可能达到目标,就输出-1.

数学方法:

  把01看成A+B个点。

  设S=A+B,X=最少要翻转次数,ti=点i翻转两次的次数。

  ①\((XK-A)/2=\sum_{i=1}^n ti\) ∴XK-A≥0且为偶数

  ②假设各点ti达到最大。

  点i为1则ti=X/2

  点i为0则ti=(X-1)/2

  得到\((XK-A)/2≤A*((X-1)/2)+B*(X/2)\)

答案不超过S,枚举判断是否符合①②条件,符合则可行。找不到的输出-1。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. typedef long long ll;
  6. using namespace std;
  7. int ng;
  8. long long A,B,K,S;
  9. int main()
  10. {
  11. freopen("b.in","r",stdin);
  12. freopen("b.out","w",stdout);
  13. scanf("%d",&ng);
  14. while(ng--)
  15. {
  16. scanf("%lld%lld%lld",&A,&B,&K);
  17. S=A+B; long long ans;
  18. for(ans=0;ans<=S;ans++)
  19. if(A==0 || ((K*ans-A)>=0 && ((K*ans-A)&1)==0 && (K*ans-A)/2<=A*((ans-1)/2)+B*(ans/2))) break;
  20. if(ans<=S) printf("%lld\n",ans); else printf("-1\n");
  21. }
  22. return 0;
  23. }

第三题 bst计数

  1. 相信大家对二叉查找树都很熟悉了,现在给你N个整数的序列,每个整数都在区间[1,N]内,且不重复。现在要你按照给定序列的顺序,建立一个二叉查找树,把第一整数作为根,然后依次插入后面的整数。
  2. 每个结点X的插入过程其实就是模拟下面的 insert(X, root)过程:
  3. insert( number X, node N )
  4. {
  5. increase the counter C by 1 //每次进来都会使C加1
  6. if X is less than the numberin node N //如果X小于结点N的值
  7. {
  8. if N has no left child //N没有左孩子把X作为N左孩子
  9. create a new node with thenumber X and set it to be the left child of node N
  10. else insert(X, left child of node N)//递归,从N左孩子插入
  11. }
  12. else (X is greater than thenumber in node N)
  13. {
  14. if N has no right child
  15. create a new node with thenumber X and set it to be the right child of node N
  16. else
  17. insert(X, right child of nodeN)
  18. }
  19. }
  20. 你要求的是:每次把序列的一个整数插入到二叉查找数后,当目前为止计数累加器C的值是多少?请把它输出。注意:第一次插入根,计数器C的值是0,你可以理解为插入根是不执行insert()操作的,其后每插入一个结点,C都类加,也就是每次进入过程insert( number X, node N ),都会执行increase the counter C by 1,使得C不断增大。

  C每次累加的其实是插入X后,X的深度。

  可以得知,depX=depXFather+1。

  如何找出X的父亲呢?

  根据排序二叉树的性质,二叉排序树的中序遍历的序列有序。假设插入X后,在二叉树的中序遍历中,X与XFather一定是相邻的。

  那么与X相邻的有两个,哪一个才是XFather?其实比较一下两点插入的时间,时间晚的一定是XFather。与X相邻表示一个是XFather,另一个一定不在XFather这棵子树中(如果在,则一定为X的儿子,但还没插入,仅此一种情况)而是XFather的Father(由性质可得),所以时间晚的就是XFather。

  直接做可以用线段树或splay过掉。

  但还有一种更优的做法。

  逆向思维,从后往前做,对于点i,1->i的序列是有序的,直接可得距离i最近的两个点,求出iFather。然后将i点删除,仍需维护1->i-1有序。可以用链表,删除点i等于

  R[L[i]]=R[i]; L[R[i]]=L[i];

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #define imax(a,b) ((a>b)?(a):(b))
  5. typedef long long ll;
  6. using namespace std;
  7. const int N=301000;
  8. int n,d[N+10],tn[N+10],L[N+10],R[N+10];
  9. int son[N+10][5],f[N+10],fa[N+10];
  10. long long ans;
  11. int main()
  12. {
  13. freopen("c.in","r",stdin);
  14. freopen("c.out","w",stdout);
  15. scanf("%d",&n);
  16. for(int i=1;i<=n;i++) scanf("%d",&d[i]),tn[d[i]]=i;
  17. for(int i=1;i<=n;i++) L[i]=tn[d[i]-1],R[i]=tn[d[i]+1];
  18. L[0]=0; R[0]=tn[1];
  19. L[n+1]=tn[n]; R[n+1]=n+1;
  20. for(int i=n;i>=1;i--)
  21. {
  22. int ll=L[i],rr=R[i];
  23. int yu=imax(ll,rr);
  24. fa[i]=yu;
  25. R[ll]=rr; L[rr]=ll;
  26. }
  27. ans=0ll; f[1]=0;
  28. for(int i=2;i<=n;i++) f[i]=f[fa[i]]+1;
  29. for(int i=1;i<=n;i++) printf("%lld\n",(ans+=f[i]));
  30. return 0;
  31. }

NOIP2017提高组模拟赛5 (总结)的更多相关文章

  1. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  2. NOIP2017提高组 模拟赛13(总结)

    NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...

  3. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  4. NOIP2017提高组模拟赛 8(总结)

    NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...

  5. NOIP2017提高组模拟赛 9 (总结)

    NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...

  6. NOIP2017提高组模拟赛 7(总结)

    NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...

  7. NOIP2017提高组模拟赛4 (总结)

    NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...

  8. 计蒜客NOIP2017提高组模拟赛(三)day1

    火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A​1​​,A​2​​,⋯,A​n​​点生命值,一次火山喷发总计 MM 轮 ...

  9. 计蒜客NOIP2017提高组模拟赛(四)day1

    T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...

随机推荐

  1. 初学ToggleButton 点击button,更换button背景图片;再次点击,恢复之前背景图

    上方的图标,R.drawable.register_checked  是选中图片 下方的图标,   R.drawable.register_unchecked 是未选中图片 默认是上方的选中效果.点击 ...

  2. C-结构体应用(10)

    结构体是用来定义多种类型的复合类型,在 C语言中与类的区别在于结构体注重的是数据而类除了数据还包含函数,第2点区别在于结构体所声明的成员默认是"public"点.而类的默认是pri ...

  3. DNS配置外网

    dnssec开启,部分dns请求为不信任链导致解析延迟或者解析失败(error显示为不信任)解决方法: vi /etc/named.conf dnssec-enable no; dnssec-vali ...

  4. Android: HowTo设置app不被系统kill掉

    有一种方法可以设置app永远不会被kill,AndroidManifest.xml 中添加: android:persistent="true" 适用于放在/system/app下 ...

  5. hdu 2795 Billboard 【线段树】

    给出一个高为h,宽为w的广告板,有n张广告需要贴,从第一行开始贴,尽量靠左,输出每个广告最后贴在哪一行的 先一直想不通这样建树是为什么 后来看到一篇题解里面的一句话“直到找到一个满足条件的叶子节点” ...

  6. SQL基本语句:2.基本表

    SQL基本表的增删改

  7. thinkphp5-----模板中函数的使用

    1.在模板中使用php函数 在thinkphp的html中,我们经常会遇到一些变量难以直接从php控制端直接处理,这些变量只有在模板中循环输出的时候处理比较合适,这个时候,我们就要在模板中使用函数 1 ...

  8. CF949B A Leapfrog in the Array 思维题,推理

    题意: Dima是一名初级程序员. 在他的工作中,他经常不断地重复以下操作:从数组中删除每个第二个元素. 有一天,他对这个问题的解决方案感到厌倦,他提出了以下华丽的算法. 假设有一长度为2n的数组,最 ...

  9. [Linux C]系统调用(system call)和库函数调用(Library functions)

    Linux 下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).系统调用实际上就是指最底层的一个调用,在 linux 程序设计里面就是底层 调 ...

  10. jQuery Validate验证(项目中使用的)

    大致结构是: <script type="text/javascript" src="<%=path %>/js/jquery-1.9.1.min.js ...