Description
给定一个
1⋯n
的排列
{pi}
,给定一个
K
,对于
Solution
求得
{pi}
的位置序列
{qi}
,则可以发现要求
{pi}
的字典序尽量小即
{qi}
的字典序尽量小。(证明请读者自行思考)
对于
{qi}
,可以交换相邻且相差大于等于
K
的两个数,那么相差小于
对应岛
{pi}
中,便是位置相差小于
K
的数的大小关系不变,所以可以对于满足
显然这样连的边是
O(n2)
的,考虑优化,发现可以只连区间内小于该数的数中最大的数,其它的边毫无意义。(想一想,为什么)那么就可以用set维护、每次lower_bound就行了。
Code
O(n2) :
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#define For(i , j , k) for (int i = (j) , _##end_ = (k) ; i <= _##end_ ; ++ i)
#define Fordown(i , j , k) for (int i = (j) , _##end_ = (k) ; i >= _##end_ ; -- i)
#define Set(a , b) memset(a , b , sizeof(a))
#define pb push_back
#define INF (0x3f3f3f3f)
#define Mod (1000000007)
using namespace std;
typedef long long LL;
template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }
template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }
int _ , __;
char c_;
inline int read()
{
for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
inline void file()
{
#ifdef hany01
freopen("permutation.in" , "r" , stdin);
freopen("permutation.out" , "w" , stdout);
#endif
}
const int maxn = 500010 , maxm = 10000000;
int v[maxm] , in[maxn] , nex[maxm] , beg[maxn] , n , k , p[maxn] , e , ans[maxn];
inline void add(int uu , int vv)
{
v[++ e] = vv;
++ in[vv];
nex[e] = beg[uu];
beg[uu] = e;
}
inline void init()
{
n = read();
k = read();
For(i , 1 , n)
p[i] = read();
For(i , 1 , n)
{
For(j , max(i - k + 1 , 1) , i - 1)
if (p[i] < p[j])
add(i , j);
For(j , i + 1 , min(i + k - 1 , n))
if (p[i] < p[j])
add(i , j);
}
}
inline void toposort()
{
priority_queue<int , vector<int> , greater<int> > q;
For(i , 1 , n)
if (!in[i])
q.push(i);
int now = 0;
while (!q.empty())
{
int u = q.top();
q.pop();
ans[u] = ++ now;
for (int i = beg[u] ; i ; i = nex[i])
{
-- in[v[i]];
if (!in[v[i]])
q.push(v[i]);
}
}
}
inline void print()
{
For(i , 1 , n)
printf("%d\n" , ans[i]);
}
int main()
{
file();
init();
toposort();
print();
return 0;
}
O(nlog2n) :
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#define For(i , j , k) for (int i = (j) , _##end_ = (k) ; i <= _##end_ ; ++ i)
#define Fordown(i , j , k) for (int i = (j) , _##end_ = (k) ; i >= _##end_ ; -- i)
#define Set(a , b) memset(a , b , sizeof(a))
#define pb push_back
#define INF (0x3f3f3f3f)
#define Mod (1000000007)
using namespace std;
typedef long long LL;
template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }
template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }
int _ , __;
char c_;
inline int read()
{
for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
inline void file()
{
#ifdef hany01
freopen("permutation.in" , "r" , stdin);
freopen("permutation.out" , "w" , stdout);
#endif
}
const int maxn = 500010 , maxm = 10000000;
int v[maxm] , in[maxn] , nex[maxm] , beg[maxn] , n , k , p[maxn] , e , ans[maxn];
inline void add(int uu , int vv)
{
// printf("%d %d\n" , uu , vv);
v[++ e] = vv;
++ in[vv];
nex[e] = beg[uu];
beg[uu] = e;
}
struct Item
{
int key , pos;
bool operator < (const Item &item) const
{
return key < item.key;
}
};
typedef set<Item>::iterator It;
It it;
inline void init()
{
n = read();
k = read();
For(i , 1 , n)
p[i] = read();
set<Item> st;
For(i , 1 , n)
{
if (i >= k + 1)
st.erase((Item){p[i - k] , i - k});
it = st.upper_bound((Item){p[i] , i});
if (it != st.end())
add(i , (*it).pos);
/* printf("%d:" , p[i]);
for (it = st.begin() ; it != st.end() ; ++ it)
printf(" %d" , (*it).key);
putchar('\n');*/
st.insert((Item){p[i] , i});
}
st.clear();
For(i , 1 , k - 1)
st.insert((Item){p[i] , i});
// putchar('\n');
For(i , 1 , n)
{
st.erase((Item){p[i] , i});
if (i + k - 1 <= n)
st.insert((Item){p[i + k - 1] , i + k - 1});
it = st.upper_bound((Item){p[i] , i});
if (it != st.end())
add(i , (*it).pos);
/* printf("%d:" , p[i]);
for (it = st.begin() ; it != st.end() ; ++ it)
printf(" %d" , (*it).key);
putchar('\n');*/
st.erase((Item){p[i - k + 1] , i - k + 1});
}
}
inline void toposort()
{
priority_queue<int , vector<int> , greater<int> > q;
For(i , 1 , n)
if (!in[i])
q.push(i);
int now = 0;
while (!q.empty())
{
int u = q.top();
q.pop();
ans[u] = ++ now;
for (int i = beg[u] ; i ; i = nex[i])
{
-- in[v[i]];
if (!in[v[i]])
q.push(v[i]);
}
}
}
inline void print()
{
For(i , 1 , n)
printf("%d\n" , ans[i]);
}
int main()
{
file();
init();
toposort();
print();
return 0;
}