zoukankan      html  css  js  c++  java
  • NOIP 普及组 2016 海港

    传送门

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

     这次比赛,上来还是死抠第一题,用了一个半小时才 AC,还是太菜了..................

    题意

      一共有 n 艘船,每艘船都有一个到港时间,每艘船上有 k 个人,这 k 个人可能来自多个不同的国家;

      求以当前船只为终了时间,在这之前的 24 小时内,到港的所有船只中所承载的乘客来自多少个国家?


    题解

    •相关变量解释

    • arrive[maxn]........................................arrive[ i ] : 第 i 艘船到港的时间
    • affect[maxn].........................................affect[ i ] : i 国籍为所影响的范围,但不包括其本身
    • vector<int >ship[maxn].........................ship[ i ] : 第 i 艘船上所承载的乘客国籍信息
    • diff[maxn].............................................差分数组 

      因为 k1+k2+.......+k2 ≤ 3×105,所以用vector存不会超内存。

    去重

      因每艘船的 k 个人可能有来自同一国家的乘客,所以先去一下重

      sort(ship[i].begin(),ship[i].end());

      ship[i].erase(unique(ship[i].begin(),ship[i].end()),ship[i].end());

    找到每艘船的乘客所能影响的最大范围

      这是什么意思呢?

      例如,第一艘船去重后,乘客分别来自 1,2,4 国家;

      由于所要求得是以当前船只为终了时间,在这之前的 24 小时内,到港的所有船只中所承载的乘客来自多少个国家;

      换句话说,当前船只的乘客只能影响这之后的 24 小时内到达的船只(不包含第 24 小时到达的船只)。

      所以第一艘船的 1 乘客的影响范围为[1,1+86400),此时,记 affect[1]=1+86400,但 1 所影响的范围不包括 affect[1] 本身;

      同理,第 2,4 乘客的影响范围也为[1,1+86400)

      当来到第二艘船的时候,去重后,乘客分别来自 2,3 国家,而当前船只到港时间为 2 ,affect[2]=1+86400 > 2,

      所以受之前船只的影响,国籍为 2 的乘客并不会对[2,1+86400)造成影响,而当前的 2 乘客可以影响的范围为 [2,2+86400),

      所以需要在之前的范围[1,1+86400)上加上范围[1+86400,2+86400),即加上[affect[2], 2+86400),并将affect[2]更新为2+86400。

    •求解

      但要如何记录以当前船只为终了时间的前 24 小时内的不同国家的乘客人数呢?

      由题干可知,t ≤ 1e9,难不成要开个 1e9 大的数组,显然是不可行的,那该怎么办呢?

      看题干,保证所输入的 t 是递增的,而 n ≤ 1e5,所以可以将 affect[ i ] 中乘客 i 的影响范围由之前的时间区间变为船只编号,如何变呢?

      还是以样例为例;

       一共有 3 艘船,每艘船的到港时间分别为 1,2,10

       第一艘船的乘客可以影响的时间范围为[1,1+86400),也就是说,只要到港时间在[1,1+86400)范围内的船只,都可以影响到,

       而后两艘船的到港时间都在这个时间范围内,所以将 affect[1]=affect[2]=affect[4]=4,意思是第一艘船的第 1,2,4乘客可以影响到前三艘船。

       来到第二艘船,其乘客国籍为 2,3,但affect[2]=4 > 2,说明在这之前的 24 小时内,有船只载有 2 国家的乘客,所以当前船只的 2 乘客能

       影响的范围变为[affect[2],end),end 指的是到港时间 >= 2+86400 最近的一艘船编号,易得 end = 4。

       其余的船只同理。

       因为每艘船只的到港时间是递增的,所以每次查找可以使用二分。

       而第 i 艘船上的每个乘客的影响范围可以用树状数组或线段树来维护;

      而我选择了一个比较方便的差分数组,何为差分数组,详情请看 http://www.cnblogs.com/widsom/p/7750656.html

     


    Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define pb push_back
     4 #define lowbit(x) (x&(-x))
     5 #define mem(a,b) memset(a,b,sizeof a)
     6 const int maxn=1e5+50;
     7 
     8 int n;
     9 int arrive[maxn];
    10 int affect[maxn];
    11 vector<int >ship[maxn];
    12 int diff[maxn];
    13 void Solve()
    14 {
    15     mem(affect,0);
    16     mem(diff,0);
    17     for(int i=1;i <= n;++i)
    18     {
    19         //t : 到港时间 >= arrive[i]+86400 的最近的一艘船的编号
    20         int t=lower_bound(arrive+i,arrive+n+1,arrive[i]+86400)-arrive;
    21         for(int j=0;j < ship[i].size();++j)
    22         {
    23             int native=ship[i][j];
    24             if(affect[native] < i)//判断一下affect[native]影响的范围是否包含当前船只 i
    25                 affect[native]=i;//如果不包含,则当前乘客的影响范围从当前船只开始
    26             diff[affect[native]]++;//当前乘客的影响范围为 [affect[native],t)
    27             diff[t]--;
    28             affect[native]=t;//更新affect[native]
    29         }
    30     }
    31     for(int i=1;i <= n;++i)
    32     {
    33         diff[i] += diff[i-1];//一遍前缀和为元素本身,也就是以当前船只为终了时间的前24小时内的来自不同国家的个数
    34         printf("%d
    ",diff[i]);
    35     }
    36 }
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     for(int i=1;i <= n;++i)
    41     {
    42         int t,k;
    43         scanf("%d%d",&t,&k);
    44         arrive[i]=t;
    45         for(int j=1;j <= k;++j)
    46         {
    47             int native;
    48             scanf("%d",&native);
    49             ship[i].pb(native);
    50         }
    51         sort(ship[i].begin(),ship[i].end());
    52         ship[i].erase(unique(ship[i].begin(),ship[i].end()),ship[i].end());
    53     }
    54     Solve();
    55 }
    56 /**
    57 5
    58 1 4 4 1 2 2
    59 2 2 2 3
    60 10 1 3
    61 100000 5 1 2 3 4 5
    62 100001 5 1 2 3 4 6
    63 **/
    View Code
  • 相关阅读:
    jsp mysql 配置线程池
    服务端 模拟 检测 攻击。。乱写
    硕思闪客精灵 7.2 破解版
    unity UnityAwe 插件
    smartfoxserver 2x 解决 Math NAN
    unity 断点下载
    java 监听文件目录修改
    wind7 64 setup appjs
    sfs2x 修改jvm 内存
    unity ngui 解决图层问题
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9859006.html
Copyright © 2011-2022 走看看