首页 > 编程知识 正文

google code jam 2008 Mousetrap 逆向

时间:2023-05-06 10:01:43 阅读:233655 作者:4018

题目大意: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.

 

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

 #include "stdafx.h"#include <string>#include <cmath>#include <queue>#include <algorithm>#include <iostream>#define PI 3.14159265358979323846264338327950288#define _clr(a,b) memset(a,b,sizeof(a))template<class T> T _abs(T a){if(a<0) a=-a;return a;}template<class T> void Get_Min(T& a,T b){ if(a>b) a=b;}template<class T> void Get_Max(T& a,T b){ if(a<b) a=b;}using namespace std;const int maxn=1000005;struct node{int left,right,value;}tree[maxn*8];void Build(int i,int left,int right){tree[i].left=left;tree[i].right=right;tree[i].value=right-left+1;if(left<right){int mid=(left+right)/2;Build(2*i+1,left,mid);Build(2*i+2,mid+1,right);}}int Insert(int i,int k){tree[i].value--;if(tree[i].left==tree[i].right) return tree[i].right;if(tree[2*i+1].value<k){return Insert(2*i+2,k-tree[2*i+1].value);}else{return Insert(2*i+1,k);}}int Search(int i,int k){if(k==tree[i].right) return tree[i].value;else if(k<=tree[2*i+1].right) return Search(2*i+1,k);else return tree[2*i+1].value+Search(2*i+2,k);}int K;int output[maxn];int main(){freopen("e://1.in","r",stdin);freopen("e://1.out","w",stdout);int T;scanf("%d",&T);for(int t=0;t<T;t++){scanf("%d",&K);Build(0,1,K);int index=1;output[1]=1;Insert(0,1);for(int i=2;i<=K;i++){int left=Search(0,index);int next=(i+left)%(K-i+1);if(next==0) next=K-i+1;index=Insert(0,next);output[index]=i;}printf("Case #%d: ",t+1);int n,temp;scanf("%d",&n);for(int i=0;i<n-1;i++){scanf("%d",&temp);printf("%d ",output[temp]);}scanf("%d",&temp);printf("%d/n",output[temp]);}return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。