• Luogu P3681 [CERC2016]舞动的盘子 Dancing Disks


    法老讲课讲到的一道妙题,觉得很有趣就写了下

    首先我们观察题意,发现原问题可以转化为一个排序问题

    考虑我们求出(f_{i,j})表示在((i,j))格子上,最多可以保证顶上的(f_{i,j})个数有序

    考虑对于所有的((i',j'),i'in[1,i],j'in[1,j],i' ot =ior j' ot= j),利用多路归并的思想,这上面的盘子都可以摆到((i,j))

    换句话说就是(f_{x,y}=sum_{i=1}^xsum_{j=1}^y f_{i,j} (i ot =xor j ot= y))

    然后(f_{6,6})上就是最后能排好序的盘子数目了,我们打个表看看:

    woc好像不行的亚子,难道就这样GG了?

    我们再仔细想一下,其实对于(f_{1,2})(f_{2,1}),它们其实是可以通过讨论来做到(f_{1,2}=f_{2,1}=2)的,这样一来还是按照上面的式子我们算一算:

    和数据范围完美契合,可以通过此题

    然后稍微讲下实现吧,首先我们肯定是考虑递归完成这个问题,设一个函数solve(x,y,tp)表示做到((x,y))且这个位置上要放成升序还是降序

    至于为什么要升降序,因为考虑我们归并的时候由于每个格子相当于是一个,因此之前的格子的升降序就要与后面的相反

    然后多路归并的话就直接用堆来维护即可,有一些小细节

    总复杂度应该是(O(6^6+36 imes n imes log 36))

    #include<cstdio>
    #include<utility>
    #include<queue>
    #include<stack>
    #include<iostream>
    #define RI register int
    #define CI const int&
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef pair <int,int> pi;
    typedef pair <int,pi> ipi;
    const int N=10;
    priority_queue <ipi,vector<ipi>,less<ipi> > big;
    priority_queue <ipi,vector<ipi>,greater<ipi> > small;
    stack <int> A[N][N],B[N][N]; int n,x;
    inline void move(const pi& A,const pi& B) //move the top disk of A to B
    {
    	int x=A.fi; while (x<B.fi) printf("%d %d D 1
    ",x++,A.se);
    	int y=A.se; while (y<B.se) printf("%d %d R 1
    ",x,y++);
    }
    inline void sort_greater(CI x,CI y)
    {
    	for (RI i=1,j;i<=x;++i) for (j=1;j<=y;++j)
    	if ((i!=x||j!=y)&&!A[i][j].empty()) big.push(mp(A[i][j].top(),mp(i,j)));
    	while (!big.empty())
    	{
    		pi nw=big.top().se; A[x][y].push(big.top().fi); big.pop(); move(nw,mp(x,y));
    		if (A[nw.fi][nw.se].pop(),!A[nw.fi][nw.se].empty()) big.push(mp(A[nw.fi][nw.se].top(),nw));
    	}
    }
    inline void sort_less(CI x,CI y)
    {
    	for (RI i=1,j;i<=x;++i) for (j=1;j<=y;++j)
    	if ((i!=x||j!=y)&&!A[i][j].empty()) small.push(mp(A[i][j].top(),mp(i,j)));
    	while (!small.empty())
    	{
    		pi nw=small.top().se; A[x][y].push(small.top().fi); small.pop(); move(nw,mp(x,y));
    		if (A[nw.fi][nw.se].pop(),!A[nw.fi][nw.se].empty()) small.push(mp(A[nw.fi][nw.se].top(),nw));
    	}
    }
    inline void solve(int x,int y,bool tp) // tp=0 less otherwise greater
    {
    	if (x==1&&y==1)
    	{
    		if (!B[x][y].empty()) A[x][y].push(B[x][y].top()),B[x][y].pop(); return;
    	}
    	if ((x==1&&y==2)||(x==2&&y==1))
    	{
    		if (B[1][1].empty()) return; int a=B[1][1].top(); B[1][1].pop();
    		if (B[1][1].empty()) return A[x][y].push(a),move(mp(1,1),mp(x,y));
    		int b=B[1][1].top(); B[1][1].pop();
    		if ((a>b)^tp) printf("%d %d %c 2
    ",1,1,x==1?'R':'D');
    		else printf("%d %d %c 1
    %d %d %c 1
    ",1,1,x==1?'R':'D',1,1,x==1?'R':'D');
    		if (tp) A[x][y].push(max(a,b)),A[x][y].push(min(a,b));
    		else A[x][y].push(min(a,b)),A[x][y].push(max(a,b)); return;
    	}
    	for (RI i=x,j;i;--i) for (j=y;j;--j) if (i!=x||j!=y) solve(i,j,tp^1);
    	if (tp) sort_greater(x,y); else sort_less(x,y);
    }
    int main()
    {
    	scanf("%d",&n); for (RI i=1;i<=n;++i)
    	scanf("%d",&x),B[1][1].push(x); return solve(6,6,1),0;
    } 
    
  • 相关阅读:
    vector.clear()无法释放内存的对策
    www.wangtam.com
    VC 控件的字体控制 若将字体设置成“宋体、仿宋—GB2312、隶书、幼圆”中的某一字体时,需将lfCharSet设置成GB2312—CHARSET才使设置的字体有效
    CPU使用率 武胜
    MySQL数据类型 转 武胜
    按小时统计的语句 转 武胜
    MYSQL 行转成列 转 武胜
    推荐一个 开源C#股票软件 武胜
    WCF传输泛型 List 对象 转 武胜
    WCF 传输大数据的问题 转 武胜
  • 原文地址:https://www.cnblogs.com/cjjsb/p/13357523.html
Copyright © 2020-2023  润新知