这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:组队训练比赛记录:contest11 [2021/08/06 13:41] 王智彪 |
2020-2021:teams:legal_string:组队训练比赛记录:contest11 [2021/08/08 14:06] (当前版本) jxm2001 |
||
---|---|---|---|
行 4: | 行 4: | ||
^ 题目 ^ 蒋贤蒙 ^ 王赵安 ^ 王智彪 ^ | ^ 题目 ^ 蒋贤蒙 ^ 王赵安 ^ 王智彪 ^ | ||
- | | B | 2 | 0 | 0 | | + | | B | 2 | 1 | 0 | |
- | | D | 0 | 0 | 0 | | + | | D | 2 | 0 | 1 | |
- | | E | 2 | 0 | 0 | | + | | E | 2 | 0 | 1 | |
| G | 0 | 0 | 0 | | | G | 0 | 0 | 0 | | ||
| I | 0 | 0 | 0 | | | I | 0 | 0 | 0 | | ||
行 100: | 行 100: | ||
} | } | ||
enter(ans); | enter(ans); | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | ===== D. Dancing Disks ===== | ||
+ | |||
+ | ==== 题意 ==== | ||
+ | |||
+ | 给定一个 $6\times 6$ 的栈,每次可以从栈 $(r,c)$ 顶部取若干个元素放入栈 $(r+1,c)$ 或栈 $(r,c+1)$ 的顶部。 | ||
+ | |||
+ | 初始时所有元素都在栈 $(1,1)$,自底向上分别是 $a_1,a_2\cdots a_n$,其中 $a_1,a_2\cdots a_n$ 构成 $1\sim n$ 的一个排列。 | ||
+ | |||
+ | 要求构造一个方案将所有元素转移到栈 $(6,6)$,且栈 $(6,6)$ 自底向上分别是 $n,n-1\cdots 1$。其中 $n\le 40000$。 | ||
+ | |||
+ | ==== 题解 ==== | ||
+ | |||
+ | 设 $f(r,c)$ 表示从 $f(r,c)$ 出发至少可以将多少个元素转移到 $(6,6)$ 且最终 $(6,6)$ 上元素有序。 | ||
+ | |||
+ | 显然 $f(6,6)=1$。而对 $f(6,5)$,假设元素自底向上为 $1,2$,考虑先移动 $2$,再移动 $1$。假设元素自底向上为 $2,1$,则同时移动 $2,1$。 | ||
+ | |||
+ | 如果有三个元素自底向上为 $3,1,2$,显然没有合法方案,所以 $f(6,5)=2$,同理 $f(5,6)=2$。 | ||
+ | |||
+ | 对其他情况,可以先将栈 $(r,c)$ 的元素从小到大排序,然后依次分配 $f(i,j)$ 个元素给栈 $(i,j)$ 处理 $(i\ge r,j\ge c,i+j\gt r+c)$,于是有 | ||
+ | |||
+ | $$ | ||
+ | f(r,c)=\sum_{i\ge r,j\ge c,i+j\gt r+c}f(i,j) | ||
+ | $$ | ||
+ | |||
+ | 最后有 $f(1,1)\ge 40000$,所以一定存在合法方案。方案构造按上述方法即可。 | ||
+ | |||
+ | 每个元素最多移动 $10$ 步,所以最多出现在 $10$ 个栈,所以总元素个数为 $O(10n)$,算上排序复杂度,总时间复杂度为 $O(10n\log n)$。 | ||
+ | |||
+ | <hidden 查看代码> | ||
+ | <code cpp> | ||
+ | const int MAXN=4e4+5,N=6; | ||
+ | int dp[N+1][N+1]; | ||
+ | int dfs1(int r,int c){ | ||
+ | if(dp[r][c])return dp[r][c]; | ||
+ | _rep(i,r,N)_rep(j,c,N){ | ||
+ | if(i!=r||j!=c) | ||
+ | dp[r][c]+=dfs1(i,j); | ||
+ | } | ||
+ | return dp[r][c]; | ||
+ | } | ||
+ | int a[MAXN],temp1[MAXN],temp2[MAXN],b[N+1][N+1]; | ||
+ | pair<int,int> p[MAXN]; | ||
+ | stack<int> st[N+1][N+1]; | ||
+ | void Move(int r1,int c1,int r2,int c2,int cnt){ | ||
+ | while(r1<r2){ | ||
+ | printf("%d %d D %d\n",r1,c1,cnt); | ||
+ | r1++; | ||
+ | } | ||
+ | while(c1<c2){ | ||
+ | printf("%d %d R %d\n",r1,c1,cnt); | ||
+ | c1++; | ||
+ | } | ||
+ | } | ||
+ | void dfs2(int r,int c,int n){ | ||
+ | if(n==0||(r==6&&c==6))return; | ||
+ | _for(i,0,n){ | ||
+ | temp1[i]=temp2[i]=st[r][c].top(); | ||
+ | st[r][c].pop(); | ||
+ | } | ||
+ | if(r+c==11){ | ||
+ | if(n==1) | ||
+ | Move(r,c,6,6,1); | ||
+ | else{ | ||
+ | if(temp1[0]<temp1[1]){ | ||
+ | Move(r,c,6,6,2); | ||
+ | st[6][6].push(temp1[1]); | ||
+ | st[6][6].push(temp1[0]); | ||
+ | } | ||
+ | else{ | ||
+ | Move(r,c,6,6,1); | ||
+ | Move(r,c,6,6,1); | ||
+ | st[6][6].push(temp1[0]); | ||
+ | st[6][6].push(temp1[1]); | ||
+ | } | ||
+ | } | ||
+ | return; | ||
+ | } | ||
+ | sort(temp1,temp1+n); | ||
+ | int lpos=0; | ||
+ | _rep(i,r,N)_rep(j,c,N){ | ||
+ | if(i==r&&j==c)continue; | ||
+ | int rpos=min(lpos+dp[i][j],n); | ||
+ | _for(k,lpos,rpos) | ||
+ | p[temp1[k]]=make_pair(i,j); | ||
+ | b[i][j]=rpos-lpos; | ||
+ | lpos=rpos; | ||
+ | } | ||
+ | _for(i,0,n){ | ||
+ | int r2=p[temp2[i]].first,c2=p[temp2[i]].second; | ||
+ | Move(r,c,r2,c2,1); | ||
+ | st[r2][c2].push(temp2[i]); | ||
+ | } | ||
+ | for(int i=N;i>=r;i--)for(int j=N;j>=c;j--){ | ||
+ | if(i==r&&j==c)continue; | ||
+ | dfs2(i,j,b[i][j]); | ||
+ | } | ||
+ | } | ||
+ | int main(){ | ||
+ | int n=read_int(); | ||
+ | _rep(i,1,n) | ||
+ | st[1][1].push(read_int()); | ||
+ | dp[6][6]=1,dp[6][5]=dp[5][6]=2; | ||
+ | dfs1(1,1); | ||
+ | dfs2(1,1,n); | ||
+ | // while(!st[6][6].empty()){ | ||
+ | // space(st[6][6].top()); | ||
+ | // st[6][6].pop(); | ||
+ | // } | ||
return 0; | return 0; | ||
} | } |