CF tracker

Edu List

https://codeforces.com/contest/1728

F. Fishermen

n个钓鱼人

第i个获得大小a[i]的鱼

他们选一个报告的顺序, 报告鱼的大小b[i], 但是可能虚报

第一个报告的 诚实报告

其它人报告的 是最小的b[i]=a[p[i]]的倍数 且 大于 前一个报告值

1
2
3
1 2 3 2 2 8 3
按顺序报 变成
1 2 3 4 4 8 9

对于所有报告顺序, 让所有报告的 sum b[i] 最小

输出sum b[i]的最小值即可

范围

n 1000

ai [1,1e6]

6s

512mb

我的思路

如果两两不同, 那么从小到大就好了, 因为b[i] >= a[i], 这是所有都取a[i] 是最小值

如果 两个相同, 那么至少一个要虚报, 那么至少 2a[i]

如果 三个相同, 那么=> a[i], 2a[i], 3a[i]

但不只是让它们不同就完了, 因为翻倍后依然可能相同

1
2 2 2 3 3
1
2 4 6 3 6

这两个6还要处理

但是一个6是变8, 一个是变9


显然 如果a 有重复n次, 那么 a,2a,…,na 一定都有的,不会中间空着, 否则把更大的来填补可以让它更小


感觉上 当倍增的时候遇到相同的, 那就让小的去增加,

但实际上

1
2
3
4
2 2 2 2 3 3
变成
2 4 6 8
3 6

如果是 2的6去变化, 那么要变成16, 不如3的6变成9

而变化, 因为上面说了不会中间空着, 那就是每次找 最大的倍数去变

这样靠差值最小来变化的贪心, 似乎是对的吗???? 但我证明不了


然后 如果这样搞, 运算量

1
600 个1, 300个2 这样大量重叠

似乎也就O(2n)?

写了下, 不出所料 样例都没过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for (ll i=a;i<(ll)n;i++)
ll read(){ll r;scanf("%lld",&r);return r;} // read
int main(){
int n=read();
map<ll,vector<pair<ll,int> > > v2tv; // {倍数, 原值}
rep(i,0,n){
int a=read();
v2tv[a].push_back({1,a});
}
map<ll,ll> v2mxt; // v 到最大倍数
ll ans=0;
while(v2tv.size()){
auto [k,arr]=*v2tv.begin();
v2tv.erase(v2tv.begin());
auto keep=arr[0];
rep(i,1,size(arr)){
auto [kt,kv] = keep; // keep {t,v}
auto [nt,nv] = arr[i]; // new {t,v}
if(!v2mxt.count(kv)) v2mxt[kv]=1; // kt 一定是1
if(!v2mxt.count(nv)) v2mxt[nv]=1; // nt 一定是1

ll nkt=v2mxt[kv]+1;
ll nnt=v2mxt[nv]+1;
if(nkt*kv < nnt*nv){ // 用keep
v2mxt[kv]=nkt;
v2tv[nkt*kv].push_back({nkt,kv});
keep=arr[i];
}else{ // 用 arr[i]
v2mxt[nv]=nnt;
v2tv[nnt*nv].push_back({nnt,nv});
}
}
printf("%d -> %lld\n",keep.second,keep.first*keep.second);
ans+=k;
}
printf("%lld\n",ans);
return 0;
}
1
2
3
4
5
6
7
8
1 -> 1
2 -> 2
3 -> 3
2 -> 4
3 -> 6
8 -> 8
2 -> 10
34

问题就在6的地方是动2还是动3, 动2是先到8再到10, 这个8 能预判吗??

并不会

閱讀全文 »

CF tracker

Edu List

https://codeforces.com/contest/1739

F. Keyboard Design

n个字符串 si, 价值ci

包含的字符都是 ‘a’~’l’ (前12个), 保证每个字符串中相邻字符不同

求 价值最大的 字符串价值集合 满足:

可以制作一个'a'~'l'出现且只出现一次的字符串t, 使得集合中所有字符串si中相邻的字符,在t上也相邻

范围

n 1000

sum |si| 2000

ci [1,1e5]

4s

1024mb

我的思路

2000 这数字有点假, 因为既然是前12个, 真的有用的配对是 11+10+9+..+1 = 12 * 11/2 = 66个

但是 66 个去做bitmask就不现实了,

12个字符,有11个连接,所以这66个中最多同时11个, 更直接就是 12!=479001600, 但是太大了

12如果是bitmask, 但似乎表示不了什么意义, 即使连成链, 不只是两头有意义, 中间的连接方式也会影响


所以其实是 n = 1000

然后每个字符串提供一个 <= 11 的连接方案(66种候选), 如果超过11一定不可能

然后 选一个集合, 使得连接方案的并 依然<= 11, 且没有任何字符连了3个, 也不构成环

样例1

1
2
3
4
3
7 abacaba
10 cba
4 db

就可以变形成

1
2
3
4
3
2 a-b a-c
2 a-b b-c
1 b-d

一个想法是, 从排列来讲是12!, 上面看到是4e8, 但是如果仅仅说连接方式, 一个连接方式 对应两个排列, 所以还是有2e8


难道真的要 暴力搜索+剪枝吗??


这个ci, 1e5 到大不小的,算和的话能有1e8, 没啥想法


想钦定一个 si被选, 但这样的 感觉还没钦定连接好, 但钦定连接就是枚举

閱讀全文 »

https://codeforces.com/contest/1743

D. Problem with random tests

给你长 n的0/1

问它的两个子串(连续)的 bit or 的最大为多少

范围

n 1e6

4s

512mb

随机生成数据 不支持 hack

我的思路

首先一个肯定是原串,为了最高位1

那么剩下的一定是从最前连续1里面开始的

1
2
3
4
11100001....
3个1 len1=3
4个0 len0=4
....

那么为了尽量高位填1, 如果len1 <= len0, 那就是都从第一个1开始,长度差为len1

1
2
3
11110001.....
len1=4
len0=3

但如果len1 > len0

那么可以选的 有从头开始,和从偏移一个开始, 这两个都会or掉第一节的0, 但是后面的情况是未知的

看着禁止hack 似乎需要上string hash的意思?


如果暴力找就是 候选的开头在

1
2
11111110001....
xxxxx 这些位置都是候选

然后对于原串, 找每个0的位置, 反过来在候选中找是否为1, 不为1则剔除候选,

这样感觉要n^2

有点想后缀数组排序, 但问题是, 这里只有原串为0的对应位置需要是1(参与比较), 而原串已经是1的则可以忽略

不会啊,干

閱讀全文 »

https://codeforces.com/contest/1749

F. Distance to the Path

给一定n点树, 初始每个点的值为0

m 个询问, 两种操作

  1. 输出点v的值
  2. 对所有到路径u..v 距离小于d的点 +k

范围

n 2e5

m 2e5

d [0,20]

k [1,1000]

4s

512mb

我的思路

如果 d = 0, 就是每次对路径上的点 增加k

似乎可以树上差分+lca维护?

但实际上 中间穿插着求一个点的值, 这样每次求值还是 O(dep[u]), 并不可行

怎么有点 树链剖分的味道?

树链剖分+线段树维护每个链???


那么 d != 0 ??

似乎会变成菊花状

閱讀全文 »

https://codeforces.com/contest/1783

F. Double Sort II

给你两个 1~n的排列a,b

每次操作可以任选一个i, 交换 a[i] 和 a[?]=i, 交换 b[i] 和 b[?]=i

求最小操作次数 的一个具体方案 让 a,b 有序

范围

n 3000

2s

512mb

我的思路

又是排列问题, 排列的交换就是和 i -> a[i] 建立的环相关, 每次交换不同的值,环变化都是1(+1/-1),

如果单独看 a,

每次只要不是操作 swap(ai,ai), 都是 环+1

所以问题变成:

找尽量少的 下标集合, 使得a,b 中的 环中被选中的个数 >= 所在环点的个数-1


3000 似乎希望n^2 的样子

考虑 如果把一个变有序

(x-x-x-x) (x-x-x) ...

另一个怎么转移

1
2
a: 1-2 3-4 5-6-7-8
b: 1-2-3-4 5-6 7-8
閱讀全文 »
0%