zoukankan      html  css  js  c++  java
  • 2018.9南京网络预选赛(J)

    传送门:Problem J

    https://www.cnblogs.com/violet-acmer/p/9720603.html

    变量解释:

      need[ i ] : 第 i 个房间含有的旧灯泡个数。

      remain[ i ] : 第 i 月后,换完满足条件的房间的旧灯泡后剩余节能灯泡的个数。

      total[ i ] : 前 i 个月换灯泡的房间数。

    题意:

      有n个房间,每个房间都有need[ i ] 个旧灯泡等着男主角去换,男主角Lpl每个月都会购买m个节能灯泡,按照输入顺序给房间换灯泡,如果当前房间满足条件,则全部换完,不满足,跳到下一个房间,重复当前步骤。

      如果当前房间并不能将新灯泡全部用完,则留着新灯泡给下个月使用。

      有q个询问,每个询问给你一个值mon,代表当前月,输出[1,mon]月换灯泡的房间个数,以及还玩灯泡后新灯泡的剩余个数。

    题解:

      最简单的方法就是暴力,从第一个月开始枚举所有的房间,知道所有的房间都换完,或来到询问的最大月份,毋庸置疑,此操作的时间复杂度为O(max_mon*n),而本题的数据范围为1~1e5,显然会超时,1e5需要的实践复杂度至多为n*logn。

      换个思路,考虑一下线段树。

      线段树中当前结点的val值存储的是左右孩子中需要换灯泡的最小值,对于第 i 个月份,优先更新满足条件的左孩子区间,当左孩子不满足条件是,回溯到右孩子区间,直到不满足条件跳出递归。

      对于满足条件的房间,在更换完灯泡后,将其val值设为最大值INF,并向上更新其父亲的val。

      具体细节,看代码............

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define ls(x) ((x)<<1)
     6 #define rs(x) ((x)<<1 | 1)
     7 #define INF 0x3f3f3f3f
     8 const int maxn=1e5+50;
     9 
    10 int need[maxn];
    11 int remain[maxn];
    12 int total[maxn];
    13 int lamps;//当前月份的新灯泡数量
    14 int sum;//前 i 个月可以换灯泡的房间数
    15 struct Node1
    16 {
    17     int l,r;
    18     int val;
    19     int mid(){
    20         return l+((r-l)>>1);
    21     }
    22 }segTree[4*maxn];
    23 void pushUp(int pos)
    24 {
    25     segTree[pos].val=min(segTree[ls(pos)].val,segTree[rs(pos)].val);
    26 }
    27 void buildTree(int l,int r,int pos)
    28 {
    29     segTree[pos].l=l,segTree[pos].r=r;
    30     if(l == r)
    31     {
    32         segTree[pos].val=need[l];
    33         return ;
    34     }
    35     int mid=l+((r-l)>>1);
    36     buildTree(l,mid,ls(pos));
    37     buildTree(mid+1,r,rs(pos));
    38     pushUp(pos);
    39 }
    40 void update(int pos,int i)
    41 {
    42     if(segTree[pos].l == segTree[pos].r && segTree[pos].val <= lamps)
    43     {
    44         lamps -= segTree[pos].val;
    45         segTree[pos].val=INF;//当前房间换完灯泡后,设置成最大值
    46         pushUp(pos>>1);//向上更新
    47 
    48         sum++;//可以更换的房间数 ++
    49         return ;
    50     }
    51     if(segTree[pos].val <= lamps)
    52     {
    53         if(segTree[ls(pos)].val <= lamps)//优先判断左孩子是否满足条件
    54             update(ls(pos),i);
    55         update(rs(pos),i);
    56     }
    57     pushUp(pos>>1);//向上更新
    58 }
    59 void init()
    60 {
    61     lamps=0;
    62     sum=0;
    63     memset(remain,0,sizeof(remain));
    64     memset(total,0,sizeof(total));
    65 }
    66 int main()
    67 {
    68     int n,m;
    69     while(~scanf("%d%d",&n,&m))
    70     {
    71         init();
    72         for(int i=1;i <= n;++i)
    73             scanf("%d",need+i);
    74         buildTree(1,n,1);
    75 
    76         for(int i=1;i <= 100000;++i)//月份最多是100000
    77         {
    78             lamps=remain[i-1]+m;
    79             update(1,i);
    80             remain[i]=(total[i-1] == n ? remain[i-1]:lamps);//更新当前月份的剩余新灯泡数量
    81             total[i]=sum;//更新前 i 个月可以更换的房间数
    82         }
    83         int q;
    84         scanf("%d",&q);
    85         for(int i=1;i <= q;++i)
    86         {
    87             int mon;
    88             scanf("%d",&mon);
    89             printf("%d %d
    ",total[mon],remain[mon]);
    90         }
    91     }
    92 }
    View Code
  • 相关阅读:
    GIT里 SSH和HTTPS的区别
    迷宫 DFS 算法
    全排列 DFS 模板
    独立岛问题的BFS,DFS求解
    红丝绒蛋糕
    BFS,DFS伪代码
    【转】一个时代的剪影----汉
    AlbertRender --- 实时&离线全局光照渲染器(一)
    【linux驱动笔记】linux模块机制浅析
    【linux驱动笔记】字符设备驱动相关数据结构与算法
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9720722.html
Copyright © 2011-2022 走看看