The Preliminary Contest for ICPC Asia Nanjing 2019

传送门

参考资料:

  [1]:官方题解(提取码:w6ny)

A.The beautiful values of the palace(思维+树状数组+扫描线)

•题意

  给你一个 $n imes n$ 的矩阵,从右上角开始转圈填充 1~n×n;
  给你 m 个坐标,只有这 m 个坐标对应的位置有权值;
  有 q 次询问,每次询问给出两个点的坐标 $(x_1,y_1),(x_2,y_2)$;
  求由这两个点形成的矩形所包围的区域中,经过处理后的权值加和;
  处理的方法是,将原权值所有数位上的数相加;

•题解

  对于每次询问,都可以处理成四部分来处理:
    $ans=f(x_2,y_2)-f(x_{1}-1,y_2)-f(x_2,y_{1}-1)+f(x_{1}-1,y_{1}-1)$;
  其中 f(x,y) 指的是由 (1,1)和(x,y) 形成的矩形中的经处理后的权值加和;
  但是由于 n 很大,所以我们不能够通过开数组预处理出所有的前缀和;
  因为没有修改操作,所以我们可以将所有询问离线处理;
  用如下数据结构存储信息:

1 struct Point
2 {
3     int x,y;
4     int f;
5     int id;
6 }p[maxn];

  其中,f 指的是当前区间是加上还是减去,如果需要加上,令 f = 1,反之,令 f = -1;
  id 指的是当前询问的编号;
  定义好数据结构后,对于第 i 次询问,我们需要记录 4 个信息:
    1.$(x=x_2,y=y_2,f=1,id=i)$
    2.$(x=x_{1}-1,y=y_{1}-1,f=1,id=i)$
    3.$(x=x_{1}-1,y=y_2,f=-1,id=i)$
    4.$(x=x_2,y=y_{1}-1,f=-1,id=i)$
  f 取值分别对应上述 f(x,y) 前的符号,如果是加入到 ans 中,f 就取值为 1,反之,取值 -1;
  除了记录询问的信息外,还需要记录 m 个有权值的坐标;
  当然,此处要将这 m 个信息和上述 4*q 个信息区分,区分的方式就是将这 m 个信息的 f 取值为 2;
  将这 q*4+m 个信息记录好后,按照 先x,在y,最后f 的规则排序,就像扫描线求矩形周长并的那道题一样;
  排序策略不对的话直接就导致整个程序 wa;
  排序策略如下:

1 bool operator < (const Point& obj)const
2 {
3     if(x != obj.x)
4         return x < obj.x;
5     else if(y != obj.y)
6         return y < obj.y;
7     else
8         return f > obj.f;
9 }

  离线好这些信息后,还需要一个重要的信息,如何快速求出 m 个有用坐标对应的值;
  你可以参考这篇博客:题解 P2239 【螺旋矩阵】
  根据对称性,很容易求出 (x,y) 所处的圈数 t=min(x,y,n+1-x,n+1-y);
  令 a1=第一圈的维数-1,a2=第二圈的维数-1,...,ai=第i圈的维数-1;
  易得 a1=n-1,a2=n-1-2,.....,ai=n-1-2*(i-1),构成了等差数列;
  令 num1=第一圈右上角的值,num2=第二圈右上角的值,...,numi=第i圈右上角的值;
  易得
    num1=1;
    num2=num1+4*a1;
    num3=num1+4*(a1+a2);
.    ..........
    numi=num1+4*(a1+a2+...+ai-1);

  因为 a 构成了等差数列,所以 numi=1+4*(a的前i-1项和)
  有了右上角的值,很容易求出当前圈数对应的左下角的值;
    leftDown=numi+2*ai;
  假设 (x,y) 在第 t 圈,其对应的值用 ans 记录;
  根据上述讲解求出 leftDown 后,找到 (x,y)与(t,t) 的曼哈顿距离,记为 cnt;
  那么 ans=leftDown+(x >= y ? -cnt:cnt);
  求出 ans 后,将其各个位的数字加起来就得到了所需的权值;
  然后,从 1 开始枚举 p 中的值,如果当前的 f = 2,那么,就将当前的权值加入到树状数组中;
  反之,更新相应的 ans=f*Sum();
  Sum() 求的是 (1,1)与当前的(x,y) 形成的矩形所包含的权值和;

•Code

  2019ICPC南京网络赛A.cpp


B.super_log

•题意

  $log_{a}^{*} (x)=egin{cases} -1 , if x < 1 \1+log_{a}^{*} (log_{a}x),if x ge 1 end{cases}$

  给出你 a,b,m,让你求解使得 $log_{a}^{*} (x) ge b$ 最小的 x,因为 x 可能很大,所以输出结果对 m 取模;

•题解

  易得 $log_{a}^{*} (a^a)=2 , log_{a}^{*} (a^{a^a})=3$,那么满足上述条件的最小的 x 为:

    $x=underbrace{a^{a^{a^{cdots}}}}_{b}$;

  那么问题就转化为了求解 $underbrace{a^{a^{a^{cdots}}}}_{b} mod m$ 的值;

  经过这两天的脑补,终于学会了这一类问题的解决方法--欧拉降幂,具体详见我的这篇博客

  因为此题中指数可能小于 $varphi(p)$,所以需要采取实战2的策略,在快速幂中判断 x 与 $varphi(p)$ 的大小关系;

•Code

  2019ICPC南京网络赛B.cpp


 F.Greedy Sequence(set+upper_bound()+思维)

•题意

  给你一个包含 n 个数的序列 a,其中 a 中存的数为 1~n 的排列;

  定义一个二维数组 s;

  s 中一共有 n 行,每行有 n 个数;

  定义 s 数组:

    ① $s_{i}[1]=i$

    ②$forall  i in[1,n],j in [2,n],s_{i,j} le s_{i,j-1}$,即 $s_i$是个非增序列;

    ③对于 $s_i$ 中的第 j( j > 1 ) 个数,$s_{i,j}$ 在 a 中的位置与 $s_{i,j-1}$ 在 a 中的位置之差的绝对值不能超过 k;

    ④ $s_i$ 中的第 j( j > 1) 个数,要尽可能的大;

    ⑤如果 $s_{i,j}$ 后,在 a 中找不到满足条件 ②③ 的数,并且 $s_i$ 不足 n 个数,用 0 填充剩余的数;

  输出 |s1|,|s2|,...,|sn|,|si|表示 s 中第 i 行包含的数的个数;

•题解(by官方)

  

•Code

  2019ICPC南京网络赛F.cpp

原文地址:https://www.cnblogs.com/violet-acmer/p/11443355.html