• [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;
    }
  • 相关阅读:
    C#界面交互Invoke的便捷写法
    C#简单线程同步例子
    输出一个数据库中所有表的数据量
    JavaScript 解析xml字符串
    图片与Byte流互转
    html中name 和 id 的区别
    JavaScript 解析xml文件
    关于序列化的使用
    js 动态创建xml串
    js动态删除节点
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2014d2t2.html
Copyright © 2020-2023  润新知