google code jam 2008 Mousetrap (逆向)

本文探讨了一种经典的卡片放置问题,给出了三种不同的解决方案,包括线段树和一种高效的模拟方法。通过对问题的深入分析,实现了从O(K^2)到O(nK)的时间复杂度优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:After reading the story, it is not hard to see that the task is clear: put card 1 in the first position, then for each card i (in the order 2, 3, ..., K), we start from the current position, and find the i-th empty spot to the right, wrap around as many times as necessary, then put card i there.

很经典的一个问题,记得当初在pku上是模拟直接过的,但这个数据量很大,模拟是不行了,自己写了个线段树。

官方分析:

1.Let S = √K, we partition the K positions into S intervals of roughly equal size (also S). 就是把区域划分为 S段,这样在寻找第k-th个emtpy的position的时候,就不用逐个位置扫描,而是逐段逐段的扫描。This solution runs in time O(K1.5).

2.把1再扩展,层上再加层,也就是线段树。

3.极其好的一个方法。虽然如果非要给这个方法一个分类,我认为这就是模拟。。。它又是逆着来的,采用了一种非常高效的方法来删除点O(n),并且寻找下一个点只需要O(1)。比如我们要查询第t个位置的数字,现在我们在第k(k<t)个位置放置了一个数字,我们不是把第k个位置删除,而是修改查询!!用t--,我们始终保持查询的是当前情况下(也即是删除插入点后)的第t个位置;当k==t的时候即是找到了对应的数字。

具体的描述:

Now let us do something different. At each step, after one position is occupied by card number i, we delete the position from the deck.

Notice that n, the number of queries is at most 100. We do not need to relabel all the positions, it is enough to do this for those n that we are interested in.

The solution can be implemented in two flavors, based on which viewpoint in the beginning of the analysis you pick. The short C++ program is, again, based on the second one, where the position (pos) changes as a pointer, and the deck does not move, except we delete one position in each step.

for (int j = 0; j < n; j++) answers[j] = -1;
for (int i = 1, pos = 0; i <= K; i++) {
  // Compute the next position, after wrap-around.
  pos = (pos + i - 1) % (K - i + 1);
  for (int j = 0; j < n; j++)
  if (answers[j] < 0) {
    if (queries[j] == pos+1) {
      queries[j] = -1; answers[j] = i;
    } else if (queries[j] > pos+1) {
      // The effect of deleting the next position.
      queries[j]--; 
    }
  }
}

You can use a trick to combine the two arrays queries[] and answers[] into one. The programs runs in Θ(n K) time.

 

最后贴个自己写的线段树的囧代码。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值