zoukankan      html  css  js  c++  java
  • JOISC2020 划水记&题解(施工中)

    (Part1) 游记

    咕咕咕

    (Part2) (solutions)

    不会的/没写完的先鸽着,补题之后再补

    目前只写了 (D1T1) (D2T2) (D3T3) (D4T1)

    (solutions) (for) (Day1)


    (D1T1)

    $description : $ LOJ链接

    $solution : $

    首先有一个(O(n^2))的朴素(dp:)

    (f[i][j][0/1])表示考虑到前(i+j)个数(,)选了(i)(A)(j)(B,)(i+j)个数选的是(A/B,)是否可行(.)

    这个(dp)的期望得分是(12)(.)

    一种想法

    一种想法是考虑构造出一个合法的方案(.)

    (f[i][0/1][0/1]) 表示在考虑序列的前(i)(,)(i)个选的是(A/B,)最多的(A/B)的数量是多少(.)

    考虑从尾到头构造方案(.) 对每个位置枚举这个位置用(A)还是用(B,)

    记当前位置为 (now,) 当前位置的字符为 (c,) 已经用了 (cntA)(A)(cntB)(B.)

    那么方案合法的条件就是 (cntA) (+) (f[now][c][0] geq n)(cntB + f[now][c][0] geq n.)

    按这种方法构造方案即可 (.) 复杂度 (O(n).)

    评测链接

    "一种想法"的正确性证明(:) ((by) (czynt) ())

    如果存在 (max({a_i,b_i})>max({a_{i+1},b_{i+1})})或者(min({a_i,b_i}) < min({a_{i+1},b_{i+1}}),)就没得选择(,)不用考虑他(.)

    现在考虑(,)如果(max({a_i,b_i}) leq min({a_{i+1},b_{i+1}}),)那就是分开的(;)

    你用这个可以把它分成若干段(;)

    现在问题就是每一段里面可不可以任意分(.)

    我们发现你可以在任意时候跳到比较高的上面去(,)就行了(.)

    (D1T2)

    $description : $ LOJ链接

    $solution : $

    一种乱搞

    把所有的矩形 cpp random_shuffle() 一下(,)然后把前(k)个矩形找出来作为起始矩形(,)后面的(n-k)个矩形用贪心的方法决策和(k)个矩形中的哪一个求交(.)

    这个做法可以过掉赛时的数据(.) 然而赛后(uoj)上就被(hack)

    LOJ评测链接 UOJ过不去hack数据的评测链接

    (solutions) (for) (Day2)


    (D2T2)

    $description : $ LOJ链接

    $solution : $

    显然题意相当于我们可以一边加入边((A_i,B_i))一边进行题目中的操作(.)

    我们把同时存在边((u,v))((v,u))的点对合并起来(,)缩成一个块(.)

    那么一条两个块之间的边((cur_x,cur_y))对答案的贡献为(size_{cur_y})

    一个大小为(s)的联通块对答案的贡献为(s*(s-1))

    在联通块之间出现可合并的点对时合并联通块(,)并把某一个联通块的所有边都合并到另一个联通块上(.)

    可以用启发式合并解决(.)复杂度(O(mlog^2m))

    评测链接(高度压行预警)

    (solutions) (for) (Day3)


    (D3T3)

    $description : $ UOJ链接

    $solution : $

    这题可以分为两个不同的子任务(:)一是(A=3,B=0,m>=n-1,)另一个是(A=2,B=6,m=n-1)


    (case1:) (A=3,B=0,m>=n-1)

    这个子任务的含义(,)就是说我有三种标记(,)在任意图的情况下每一步都必须沿着最短路走(.)

    以下为了方便(,)把标记看成颜色(,)不同的标记即不同的颜色(.)

    我们考虑以终点(0)为根对给定的图进行(BFS.)(dis_i)(0->i)的最短路(.)

    (BFS)之后(,)对于图中的一条边 $ (u,v) $ 一定有 (|dis_u-dis_v] leq 1)

    换言之(,)我们(BFS)后的图就是有若干"层"点(() 我们把(dis_x)相同的点看做一层 (),)其中层与层之间有连边(,)同时一层点的内部也有相互连边(.)

    那么我们需要保证(,)对于每个点我们必须能够让它能判断下一步往哪个标记走(,)
    并且保证下一步一定走向下一层点(,()(dis_x)更小的点(,)也就是说(,)不能走到(dis)更大的点(,)也不能通过这一层内部的边走到(dis)相同的点().)

    所以我们就可以知道(:)

    (1.)每一层的点与下一层的所有连边应该是同种颜色(;)

    (2.)每一层内部的连边的颜色应当和前一层连接到这一层的边颜色相同(.)

    最后还剩下一个问题(:)对于一个点(,)
    我可能会在int Move(vector<int> y) (get)到两种可能的颜色(,)但我要怎么(check)哪一种颜色是我这一步需要走的呢(?)

    有一个(可能)比较精妙的构造 (:) 我们可以给颜色设计一个类似石头剪刀布的优先级 (() 比如 (,) (0>1,1>2,2>0) ().)

    这样我们就可以解决这个(case)(.)

    关键代码(:)

    //Anthony 比较长,就不贴了,评测链接里有代码
    //Catherine
    namespace subtask0{
    	int A,B;
    	int work(std::vector<int>y){
    		int i,s = 0,a = -1,b = -1;
    		for (i = 0; i < A; ++i) if (y[i]){ if (a == -1) a = i; else b = i; }
    		if (b == -1) return a;
    		//这里的a和b是和当前点相邻的边的两种颜色
    		if (a > b) swap(a,b);
    		if (!a && b == 1) return 0;
    		if (a == 1 && b == 2) return 1;
    		if (!a && b == 2) return 2;
    	}
    }
    

    (case2) (:) (A=2,B=6,m=n-1)

    这个子任务呢(,)就是要求我们给一棵以 (0) 为根的树上黑白染色(,)然后通过不超过 (dis+6) 步能成功走到点 (0) (.)

    由于是一棵树(,)所以对于一个节点(x,) (x)的父节点只有一个(,)而子节点可以有一个或多个(.)

    如果说一个点的 (u) 度数 (>2) (() 换言之 (,) (u) 有不止一个子节点 (),)

    那么我们就必须 (u) 与儿子之间的所有边 设成同一个颜色 (,) 且和 $ $ (u) 与父亲之间的边 颜色不同 (.)

    这样的话(,)当我走到的点(degree>=3)(degree = 1)(,)我就能够简单的判断方向 (,) 知道下一步应该走哪里 (.)

    问题来了 (!) 如果有一条直上直下的长链(,)链上所有点的度数都是 (2,) 怎么办啊 (?)

    因为度数为 (2,) 而根据上述的连边方式是不能在 (6)次错误之内 判断方向的(,)所以我们要对现有的方案进行一些修改 (.)

    具体来说(,)我们是要对链进行一些修改(,)使得在链上可以快速判断方向(.)

    通过一些人类智慧(,)我们有了一个字符串(010011.)

    这个字符串有着很好的性质(:)我们一旦(get)到了他的一个循环同构串(,)就可以直接判断是正向还是反向(.)

    这个字符串怎么用呢(……)

    我们把这个串的循环挂在链上 (,)(010011010011...)(100110100110...)

    因为(B=6) (,) 所以我们只能向错误的方向最多走 (3)(.)

    但是我们发现走了三步之后正好能(get)到串的 (5) 个字符 (,) 那么这个串的一个循环同构串也就被唯一确定了 (.)

    至此我们能够在 (3) 步之内正确判断一条链上的方向 (.) 如果中途碰到度数 (= 1) (or) (geq 3) 的点我们就可以直接(check)(.)

    那么这个 (case) 也被我们解决了 (.)

    //这个case代码量较大,不适合贴在博客里,但是评测链接里有代码
    

    评测链接

    (solutions) (for) (Day4)


    (D4T1)

    $description : $ 目前只有(atcoder)上有(,) (loj/uoj) 上都没有 (,) 就不挂链接了

    $solution : $


    一种十分暴力但是非常难写的做法

    我们考虑对于每种颜色强行求出如果要包含它(,)需要的颜色种类有多少种(.)

    对每种颜色建出虚树(.)然后如果颜色(c)包含了虚树上的一个点(,)那么就向那个点所在的颜色连边(.)

    最后(,)如果颜色(u)在图上能走到另一个颜色(v,)说明颜色(u)需要包含的颜色集合中有(v.) 那么我们只要求出缩点之后的图就可以解决问题了(.)

    现在我们有(O(n))个 一个点 往 树上的一条链 连边的操作(.)考虑优化建图(.)

    树剖(,) (st) 表优化建图 (,) 最后 (tarjan) 缩点解决(.)

    时空复杂度为(O(nlogn),)代码长度很长 (() (5)(K) ()) (,) 空间很紧(.)

    评测链接1(空间500MB)

    评测链接2(空间487MB)


    一种简易方便的做法

    咕咕咕

  • 相关阅读:
    JNI_Z_02_函数参数_JNIEnv*_jclass_jobject
    JNI_Z_01_获取Clazz
    文章网址
    nginx安装,反向代理配置
    排序的hashmap(guava)
    Unirest-拼装http请求发送rest接口
    mac远程连接windows
    java class遍历属性
    mongodb mongotemplate聚合
    java tar.gz文件生成
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13581270.html
Copyright © 2011-2022 走看看