2018-2019, ICPC, Asia Yokohama Regional Contest 2018 gym102082
简要题解
B
首先先对原序列排序
预处理出一个\(nxt_{i,j}\)表示选了\(a_i\),\(a_j\),下一个要选谁,这个可以对于j从大往下枚举i,那么nxt就是单调的
然后枚举开头的两项,根据nxt数组找到第三项
记忆化一下一个\((i,j)\)只会被跳过一次即可
复杂度\(O(n^2)\)
C
算出每个人到终点的时间
其实题目可以支持的操作就是给某一个数加一,然后要使得所有数互不相同
简单模拟一下就可以了
D
建立出序列自动机
然后bfs,记录状态\((x,y)\),表示第一个串走到x,第二个串走到y即可
字典序最小在bfs下优先走0就可以了
当然序列自动机基本都可以通过其他dp方法解决
E
存在欧拉回路的条件一共有两个:
1.图是联通的
2.所有点的度数都是偶数
- 实现思路
- 首先,把所有能加的边都提取出来,并对每一条边设一个未知数 xi。
- 构建一个(异或)方程组,如果边 i 连接 u 和 v,则 \(A_{u,i} = A_{v,i}\) = 1
- 如果点 u 的度数为奇数,则 B[u] = 1
- 对这个方程组进行高斯消元,如果存在 0 = 1 的情况则无解,否则将自由元全部设为 0,将主元设为这一行对应的 B 值
- 连完所有边之后,如果还剩下大于 2 个连通块,则直接在这些连通块之间连一个环出来,如果只剩一个,则不需要做任何操作
- 如果剩下两个连通块:
- 如果两个连通块都有多余两个点,则设 a, b 在第一个,c, d 在第二个:
- 连边 a--c b--c a--d b--d 即可
- 如果其中一个连通块只有一个点 a
- 如果另一个连通块没有增加任何一条边
-
如果这个连通块不是完全图,设 b--c 这条边没连:
-
连边 a--b a--c b--c 即可
-
否则,无解。
- 否则,找到一条增加的边 (b, c),删掉,连接 a--b a--c。
G
不妨先考虑最小的数,这个数要么去往最左边要么去往最右边
对于相同的数,枚举一个断点,左侧的数全部去最左边,右侧的数全部去最右边
当一个数被移到两端以后对后面数字显然没有任何影响
用数据结构维护一下要移多少步即可
H ?
不太清楚怎么做
这里大致翻译一下一个老哥的做法
Submission #51924100 - Codeforces
先对点进行排序,从上往下,从左往右扫
尝试去给每个节点上色
如果存在一种可以用的颜色直接上即可
否则尝试给相邻的节点换颜色,定义一个函数,表示将p这个节点的颜色从now染成pre,然后对不断对相邻且矛盾的点进行修改
有一点将两种颜色翻转的味道
然后solve就是填色,如果填不了,就尝试去换颜色,直到填的下去为止
复杂度感觉上是O(n^2),但实际上不太清楚。正确性也不太清楚..
反正跑得过
void rever(int p,int pre,int now)
{
col[p]=pre;
for(auto x:G[p])
{
if(col[x]==pre)
{
rever(x,now,pre);
}
}
}
void solve(int p)
{
col[p]=find_col(p);
if(col[p]) return ;
for(auto x:G[p])
{
if(!col[x]) continue;
for(int i=1;i<=4;i++){
rever(x,i,col[x]);
col[p]=find_col(p);
if(col[p]) return ;
}
}
}
I
题意本质上就是叫你维护一个线形基,然后rank就是线形基里面元素个数
然后问你每一次修改某个元素的一位,会使得rank变大还是变小还是不变
考虑如果求出,除了第\(i\)个元素以外的线形基
可以用类似分治的方法,solve(l,r)表示插入了除l,r以外的所有元素的线形基,递归左边时把右侧所有元素插进去,递归右边时把左侧所有元素插进去
然后考虑如果对于一个串求出修改某一位之后能够对当前线形基进行改变
线形基进行一定的规则化,即如果第\(i\)位有元素,且第\(j\)位也有元素,且第\(i\)位的元素第\(j\)位也有1,则将该1消去。这样以后,第i位元素往后的1,一定都是在线形基里面没有元素。
先把原串在线形基里面消元
不妨设当前修改的是第i位
1.如果原串插不进去,即消除来的是0
此时可以看作是插入\(2^i\),检查一下线形基里第i位的元素是不是恰好是\(2^i\)即可
如果该位是,则为不变。否则位增加,因为往后的1在线形基里一定没有元素
2.原串插进去了
如果当前位本来是0,现在变成了1。那么除非变完之后,和在第i位的元素恰好相同,否则一定可以,即不变。
如果当前位本来是1,现在变成了0。那么除非变完之后,变成了0,否则一定可以,即不变。
其余为减少
但这样复杂度是\(O(n^3logn/w)\)的
有一些更为标准的做法
Submission #54834591 - Codeforces
Submission #66225709 - Codeforces
但我还没看懂他们在写什么,在看懂的路上了
J
玩一下可以发现
生成树大小就是dfs序相邻两个点的距离之和(首尾相连)加起来除以2
其实这也是一个经典结论了
用set维护一下集合即可
K
先考虑如果求出当前的答案
排序后,对A从小到大枚举,找到B比当前值大的最小的一个数
维护一个双指针即可O(n)出解
考虑字典序最大
需要保证填入的数不会使得答案发生改变。
对于每一位,如果赢的话,合法的一定是B中比A大的一段“前缀”。如果输的话,合法的一定是B最小开始的一段前缀。
二分去找最大的一个即可。