codeforces 220c Little Elephant and Shifts

来源:互联网 发布:ubuntu 14.04 lnmp 编辑:程序博客网 时间:2024/05/18 01:19

       很少遇到经典的题目,这个不算经典但是却也非常精彩。题目

题目大意:给定两个两个1-n的排列,定义两个排列的距离为:所有相同数字之间距离的最小值,More formally, it's such minimum|i - j|, that ai = bj.定义Acyclic shift number i (1 ≤ i ≤ n) of permutationb consisting from n elements is a permutationbibi + 1...bnb1b2...bi - 1. Overall a permutation hasn cyclic shifts. 输出者n个cyclic shifts的距离。

eg:

42 1 3 43 4 2 1
输出 2 1 0 1

解题思路:由于n很大(10^5),所以,我想到应该是O(nlogn)的算法,我想到线段树,但是怎么也想不出来怎么维护,后来和同学讨论,想到一种方法:第一个序列为A,第二个需要旋转的为B,即使维护B中的值是在A中对应值得左边还是右边,如果是左边,那么旋转之后距离+1,右边则-1,如果我们维护这两个优先队列,当-1的元素-到0时,则插入到左边的序列中,右边的序列删除。对于头上需要移动到最后的元素,则插入操作,和删除操作。说的可能有点乱!

但是有几个难点:1)删除操作怎么处理?优先队列,不管是用堆实现还是stl都没有删除的操作,我的方法是,每一个元素都有一个时间戳,如果出队的元素时间戳过时了,那么直接出对,不用管。这样就达到了删除的作用

2)对于整个优先队列的+1和-1操作,可以考虑使用延迟加减的操作,理解就是,既然整个都+1相当于没有+1,也就是出队的时候在+1就是了,这样的话,插入需要注意了,插入前要加减这个延迟,才能保证出队是的值的正确性。

code:

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <queue>#include <stdlib.h>using namespace std;#define N 100010int dat1[N],dat2[N];int pos[N];struct note{    int val,time,index;    note(){}    note(int _v,int _t,int _i):val(_v),time(_t),index(_i){}};struct cmp{    bool operator() ( note a, note b )    {        return a.val > b.val;    }};int _time[N];int main(){    int n;    while(cin >> n)    {        for(int i = 0;i < n;i++) scanf("%d",&dat1[i]);        for(int i = 0;i < n;i++) scanf("%d",&dat2[i]);        for(int i = 0;i < n;i++) pos[dat1[i]] = i;        priority_queue < note ,vector<note> ,cmp > l_queue,r_queue;        memset(_time,0,sizeof(_time));        for(int i = 0;i < n;i++)        {            //在原数的左侧            if(pos[ dat2[i] ] >= i) l_queue.push( note(pos[dat2[i]] - i,0, pos[ dat2[i] ] ) );            else r_queue.push( note(i-pos[dat2[i]],0, pos[ dat2[i] ] ) );        }        int t = 0;        int now_time = 1;        for(int i = 0;i < n;i++)        {            while(l_queue.empty() == 0 && l_queue.top().time != _time[l_queue.top().index]) l_queue.pop();            while(r_queue.empty() == 0 && r_queue.top().time != _time[r_queue.top().index]) r_queue.pop();            if(l_queue.size() == 0) cout << r_queue.top().val - t << "\n";            else if(r_queue.size() == 0) cout << l_queue.top().val + t << "\n";            else cout << min(l_queue.top().val+t,r_queue.top().val-t) << "\n";            if(i == n-1) continue;            t++;            int ttt = dat2[i];            r_queue.push(note(n-1 - pos[ttt] + t,now_time,pos[ttt] ));            _time[pos[ttt]] = now_time++;            while(r_queue.empty() == 0 && r_queue.top().val - t == 0)            {                note tt = r_queue.top();r_queue.pop();                tt.val = 0-t;                l_queue.push(tt);            }        }    }    return 0;}

ps:我很喜欢这个题~