A. Latin Square
考虑维护三元组 \((i,j,a_{i,j})\)。例如:R
操作就是变成了 \((i,j+1,a_{i,j})\);I
操作就是变成了 \((i,a_{i,j},j)\)。时间复杂度 \(O(m+n^2)\)。
Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace asbt{
const int maxn=1e3+5;
int T,n,m,a[maxn][maxn],b[maxn][maxn];
string s;
int main(){ios::sync_with_stdio(0),cin.tie(0);cin>>T;while(T--){cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<n;j++){cin>>a[i][j];a[i][j]--;}}int pa=1,pb=2,pc=3;int da=0,db=0,dc=0;cin>>s;for(char opt:s){switch(opt){case 'R':{db++;break;}case 'L':{db--;break;}case 'D':{da++;break;}case 'U':{da--;break;}case 'I':{swap(pb,pc),swap(db,dc);break;}default:{swap(pa,pc),swap(da,dc);break;}}}for(int i=0;i<n;i++){for(int j=0;j<n;j++){int aa=pa==1?i:pa==2?j:a[i][j];int bb=pb==1?i:pb==2?j:a[i][j];int cc=pc==1?i:pc==2?j:a[i][j];aa=((aa+da)%n+n)%n;bb=((bb+db)%n+n)%n;cc=((cc+dc)%n+n)%n;b[aa+1][bb+1]=cc+1;}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cout<<b[i][j]<<' ';}cout<<'\n';}}return 0;
}
}
int main(){return asbt::main();}
B. Even Split
显然最小极差是可以二分出来的。check 不容易直接想,先考虑弱化版,假设已经知道了最短、最长的区间长度 \([x,y]\) 如何 check,线性扫一遍维护右端点区间即可。考虑如果这个 \(x\) 太大,即 \(\exist i,l>a_{i+1}\),则合法的 \(x'\) 必然满足 \(x'<x\);如果 \(y\) 太小,即 \(\exist i,r<a_i\),则必然满足 \(y'>y\),即 \(x'>x\),于是再二分 \(x'\) 即可。
考虑构造答案,先正向扫一遍使每一段满足最小值的限制,再反过来扫一遍满足最大值的限制即可,构造出的解必然合法。
Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace asbt{
const int maxn=1e5+5;
int n,m,a[maxn],mn,mx,b[maxn];
il int chk(int x,int y){mn=x,mx=y;int l=0,r=0;for(int i=1;i<=n;i++){if(l+x>a[i+1]){return 1;}if(r+y<a[i]){return -1;}l=max(a[i],l+x);r=min(a[i+1],r+y);}if(l>m){return 1;}if(r<m){return -1;}return 0;
}
il bool check(int x){int l=0,r=m;while(l<r){int mid=(l+r)>>1;switch(chk(mid,mid+x)){case 1:{r=mid;break;}case -1:{l=mid+1;break;}default:{return 1;break;}}}return 0;
}
int main(){ios::sync_with_stdio(0),cin.tie(0);cin>>m>>n;for(int i=1;i<=n;i++){cin>>a[i];}a[n+1]=m;int l=0,r=m;while(l<r){int mid=(l+r)>>1;if(check(mid)){r=mid;}else{l=mid+1;}}check(l);for(int i=1;i<=n;i++){b[i]=max(b[i-1]+mn,a[i]);}b[n]=m;for(int i=n;i;i--){b[i-1]=max(b[i-1],b[i]-mx);}for(int i=1;i<=n;i++){cout<<b[i-1]<<' '<<b[i]<<'\n';}return 0;
}
}
int main(){return asbt::main();}