题目:http://blog.youkuaiyun.com/wukonwukon/article/details/7945526
代码:http://blog.youkuaiyun.com/acm_ted/article/details/7943188
官方题解:http://codeforces.com/blog/entry/5177
给定两个两个1-n的排列,定义两个排列的距离为:所有相同数字之间距离的最小值,More formally, it's such minimum |i - j|, that ai = bj.定义A cyclic shift number i (1 ≤ i ≤ n) of permutation b consisting from n elements is a permutation bibi + 1... bnb1b2... bi - 1. Overall a permutation has n cyclic shifts. 输出者n个cyclic shifts的距离。
eg:
4 2 1 3 4 3 4 2 1输出 2 1 0 1
220C - Little Elephant and Shifts
Each of the shifts can be divided into two parts — the right (the one that starts from occurrence 1) and the left (the rest of the elements). If we could keep minimal distance for each part, the minimal of these numbers will be the answers for the corresponding shift. Lets solve the problems of the right part, the left will be almost the same.
Let we have some shift, for example 34567[12] and the permutation A is 4312765 and B is 2145673, then shifted B is 4567321. Let we keep two sets (S1 and S2). The first will keep all the distances from integers in current left part to the corresponding positions in A(for the example above, it is \texttt{2, 4}). When you come to the next shift, all integers in S1 should be decreased by 1 (that is because all distances are also decreased by 1). But now some integers in set may be negative, when any negative integer occures (it always will be -1) you need to delete it from S1 and put 1 to the S2. Also after shifting to the next shifts, all integers in S2 must be increase by 1. After that, for any shift, the answer will be minimum from the smallest numbers in S1 and S2.
It was very useful to use standart "set" in C++.
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define MAX 100010
int a[MAX],b[MAX],hashx[MAX],d[MAX];
multiset<int> s;
int main()
{
int n,t,res;
scanf("%d",&n);
for(int i=0; i<n; ++i)
{
scanf("%d",a+i);
hashx[a[i]]=i;//存放数字在a中的位置
}
for(int i=0; i<n; ++i)
{
scanf("%d",b+i);
s.insert(i-hashx[b[i]]);//插入相同数字的距离
}
for(int i=0; i<n; ++i)
{
multiset<int>::iterator it=s.lower_bound(i);//查找大于等于i的第一个数
res=0xfffff;
if(it!=s.end()) res=min(res,(*it)-i);//非负数中最小的数的绝对值
if(it!=s.begin()) res=min(res,i-(*(--it)));//负数中的最大的数的绝对值
printf("%d\n",res);
//模拟旋转
t=b[i];
s.erase(s.find(i-hashx[t]));
s.insert((i+n)-hashx[t]);
}
return 0;
}