D
题意
从左上角开始走,不能走重复的路,走确切
条路,给出方案。
方案的形式是多个
,每个
是由
和不超过
的字符串组成,字符串表示怎么走,
即走多少个这样的字符串。
【比如
可以表示为
】
要求这样的数量不超过
题解
比赛的时候没想到能跑满。神经石乐志。
考虑左上,能出去一次回来一次出去一次再回来一次。
如果要跑满的话必定,它要作为终点。
我们考虑对于第一列,它往下走一格,然后把第二行左右都走一遍。一直走到底。
会到
的地方,并且把所有
的左右都走了。
然后一直往上走到
同理,往右一格,然后走满所有的上下,最后回来。
这样每次用第一列的上下换了所有的左右(除了第一行),然后用第一行的左右换了所有的上下。
一共两次,每次是
所以次数是
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
typedef long long ll;
using namespace std;
const ll mod = 1e9+7;
const int maxn = 3e5+500;
int n,m,k;
vector<pair<int,char> >G;
void print(){
puts("YES");
cout<<G.size()<<endl;
for(auto it:G){
cout<<it.first<<" "<<it.second<<endl;
}
}
void del(int cnt,char ch){
if(cnt==0)return ;
if(k<=cnt)G.push_back(make_pair(k,ch)),print(),exit(0);
else G.push_back(make_pair(cnt,ch)),k-=cnt;
}
int main(){
cin>>n>>m>>k;
del(n-1,'D');
for(int i=1;i<n;i++)del(m-1,'R'),del(m-1,'L'),del(1,'U');
for(int i=1;i<m;i++)del(1,'R'),del(n-1,'D'),del(n-1,'U');
del(m-1,'L');
puts("NO");
}
E
题意
对于一个四色矩阵,多个询问,询问子矩阵中最大的四色块
四色块是:
题解
首先我们得求出有哪些四色块,我们可以以中间点为标志代表一个四色块,比如红色右下角。
怎么快速求对于每个方块作为中心点的时候能得到的最大四色块呢?
首先枚举每个方块是
。其实我们可以暴力扩展,维护一个二维前缀和判断
个长条,比如红色就是左边和上边必须是红色,一层一层往外扩展。复杂度是
我们发现四色块肯定是越大越可能不符合,越小越可能符合,并且一旦符合小的一定符合。
所以我们可以二分。
再考虑怎么快速求子矩阵中最大四色块,首先我们知道上面那个值,但是他可能会超过子矩阵大小,所以边界是一定限制的。这里也用到了二分(我觉得比较巧妙)。
二分答案,从而确定了中心点的范围,比如询问
,你需要判断
是不是答案。
首先中心点一旦在
,肯定不是答案,哪怕他能形成
的四色块。因为边界限制了它。他的答案最多也只是
。
所以在我们判断答案 合法与否的时候,上左边界应该是 ,下右边界应该是 ,这样能够保证不会被边界限制,判断此时新的子矩阵中的最大值,如果大于等于 说明能取到答案。
显然
越大,新子矩阵范围越小,最大值越小;
越小,新矩阵范围变大,最大值越大,显然一定满足要求。
至于矩阵最值,用二维
(原理就是二维分别一维
)
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
typedef long long ll;
using namespace std;
const ll mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const int maxn = 3e5+500;
int n,m,q;
const int Log = 12;
const int N = 600;
int maxv[Log][Log][N][N];
int pre[N],val[N][N],sum[N][N][4];
char str[N][N];
void init(){
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)maxv[0][0][i][j]=val[i][j];
pre[2]=pre[3]=1;
for(int i=4,up=max(n,m);i<=up;i++)pre[i]=pre[i>>1]+1;
int up1=pre[n]+1,up2=pre[m]+1;
for(int l1=0;l1<=up1;l1++){
for(int l2=0;l2<=up2;l2++){
if(!l1&&!l2) continue;
for(int i=1;(i+(1<<l1)-1)<=n;i++){
for(int j=1;(j+(1<<l2)-1)<=m;j++){
if(l2)maxv[l1][l2][i][j]=max(maxv[l1][l2-1][i][j],maxv[l1][l2-1][i][j+(1<<(l2-1))]);
else maxv[l1][l2][i][j]=max(maxv[l1-1][l2][i][j],maxv[l1-1][l2][i+(1<<(l1-1))][j]);
}
}
}
}
}
int query(int x1,int y1,int x2,int y2){
int p=pre[x2-x1+1],q=pre[y2-y1+1];
int ans=-inf;
ans=max(maxv[p][q][x1][y1],maxv[p][q][x1][y2-(1<<q)+1]);
ans=max(ans,max(maxv[p][q][x2-(1<<p)+1][y1],maxv[p][q][x2-(1<<p)+1][y2-(1<<q)+1]));
return ans;
}
bool check(int x1,int x2,int y1,int y2){
if(x1>=1&&x1<=n)
if(x2>=1&&x2<=n)
if(y1>=1&&y1<=m)
if(y2>=1&&y2<=m)return true;
return false;
}
int getsum(int x1,int y1,int x2,int y2,int id){
if(!check(x1,x2,y1,y2))return 0;
return sum[x2][y2][id]-sum[x1-1][y2][id]-sum[x2][y1-1][id]+sum[x1-1][y1-1][id];
}
bool checkval(int x,int y,int L){
int x1,y1,x2,y2;
x1=x-L+1,y1=y-L+1,x2=x,y2=y;
if(getsum(x1,y1,x2,y2,0)<L*L)return false;
x1=x-L+1,y1=y+1,x2=x,y2=y+L;
if(getsum(x1,y1,x2,y2,1)<L*L)return false;
x1=x+1,y1=y-L+1,x2=x+L,y2=y;
if(getsum(x1,y1,x2,y2,2)<L*L)return false;
x1=x+1,y1=y+1,x2=x+L,y2=y+L;
if(getsum(x1,y1,x2,y2,3)<L*L)return false;
return true;
// cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;
// cout<<getsum(x1,y1,x2,y2,0)<<endl
}
bool checkans(int x1,int y1,int x2,int y2,int mid){
// cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<" "<<mid<<endl;
if(x1<=x2&&y1<=y2){
if(query(x1,y1,x2,y2)>=mid)return true;
else return false;
}
else return false;
}
int main(){
cin>>n>>m>>q;
FOR(i,1,n)scanf("%s",str[i]+1);
FOR(i,1,n)FOR(j,1,m){
FOR(k,0,3)sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k];
if(str[i][j]=='R')sum[i][j][0]++;
if(str[i][j]=='G')sum[i][j][1]++;
if(str[i][j]=='Y')sum[i][j][2]++;
if(str[i][j]=='B')sum[i][j][3]++;
}
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
int l=0,r=min(n,m),ans;
while(l<=r){
int mid=(l+r)>>1;
if(checkval(i,j,mid)){
l=mid+1;
ans=mid;
}
else r=mid-1;
}
val[i][j]=ans;
//cout<<val[i][j]<<" ";
}
//cout<<endl;
}
init();
for(int i=1;i<=q;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int l=0,r=min(n,m),ans;
while(l<=r){
int mid=(l+r)>>1;
if(checkans(x1+mid-1,y1+mid-1,x2-mid,y2-mid,mid)){
l=mid+1;
ans=4*mid*mid;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}