AGC 001 F Wide Swap (拓扑排序)

来源:互联网 发布:手机淘宝怎么开店铺 编辑:程序博客网 时间:2024/05/21 22:48

Description

给定一个1n的排列{pi},给定一个K,对于pi=pj+1|ij|K可以交换pipj的值,求经过变换可以得到的最小的字典序

Solution

求得{pi}的位置序列{qi},则可以发现要求{pi}的字典序尽量小即{qi}的字典序尽量小。(证明请读者自行思考)
对于{qi},可以交换相邻且相差大于等于K的两个数,那么相差小于K的数的相对位置是不变的。
对应岛{pi}中,便是位置相差小于K的数的大小关系不变,所以可以对于满足|ij|Kpipjijij连一条边,然后就可以建立一个拓扑图,求其字典序最小的序列。
显然这样连的边是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;}
原创粉丝点击