[Noi2014]随机数生成器

来自FallDream 的博客,未经允许,请勿转载, 谢谢。


 

n,m<=5000

 

前面生成的一堆数列 意义不明  实际上就是给你一个矩阵求排序后字典序最小的路径序列

发现(1,1)->(n,m)在选了(x,y)之后就变成了选(1,1)->(x,y)和(x,y)->(n,m)

所以直接从1开始贪心,能选就选,用数组维护一下每一行可选的左右区间就行了。

但是我菜 所以我写了一个set维护矩形,然后二分..

#include<iostream>
#include<cstdio>
#include<set>
#include<algorithm>
#define MN 25000000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int tot,x,a,b,c,d,n,m,q,s[MN+1],pos[MN+1],Q[10001],top=0;
struct sq{int x1,y1,x2,y2;
    bool operator<(const sq&b)const{return  y2==b.y2?x2<b.x2:y2<b.y2;}
    bool in(int x,int y)const{return x>=x1&&x<=x2&&y>=y1&&y<=y2;}
};
set<sq> st;
bool mark[MN+1];
int main()
{
    x=read();a=read();b=read();c=read();d=read();
    n=read();m=read();tot=n*m;q=read();
    for(register int i=1;i<=tot;++i) s[i]=i;
    for(register int i=1;i<=tot;++i)
        x=(1LL*a*x*x+1LL*b*x+c)%d,swap(s[i],s[x%i+1]);
    for(register int i=1;i<=q;++i) 
    {
        int x=read(),y=read();
        swap(s[x],s[y]);    
    }
    for(register int i=1;i<=tot;++i) pos[s[i]]=i;
    mark[Q[++top]=s[1]]=1;mark[Q[++top]=s[tot]]=1;st.insert((sq){1,1,n,m});
    for(register int i=1;i<=tot;++i) if(!mark[i])
    {
        int x=(pos[i]-1)/m+1,y=(pos[i]-1)%m+1;
        set<sq>::iterator it = st.lower_bound((sq){0,0,x,y});
        if(it->y2==y&&it->x2<x) ++it;
        if(it!=st.end()&&it->in(x,y))
        {
            Q[++top]=i;sq th=*it;
            st.erase(it);
            if(th.x1!=x||th.y1!=y)st.insert((sq){th.x1,th.y1,x,y});
            if(th.x2!=x||th.y2!=y)st.insert((sq){x,y,th.x2,th.y2});
            for(register int j=x+1;j<=th.x2;++j)
                for(register int k=th.y1;k<y;++k)
                    mark[s[(j-1)*m+k]]=1;
            for(register int j=th.x1;j<x;++j)
                for(register int k=y+1;k<=th.y2;++k)
                    mark[s[(j-1)*m+k]]=1;
        }
    }
    sort(Q+1,Q+top+1);
    printf("%d",Q[1]);
    for(register int i=2;i<=top;++i) printf(" %d",Q[i]);\
    return 0;
}

 

posted @ 2017-05-02 18:10  FallDream  阅读(339)  评论(0编辑  收藏  举报