Preface
這次難度感覺挺平均的,前面的題不水,後面的題也不毒瘤(可能是因為我做的不夠後面)
A. Special Characters
開局構造題。
因為特殊字元一定是成對出現的(包括兩邊的,可以分類討論思考一下),所以只有 \(n\) 為偶數的時候才有解。
然後直接以 AABBAABB...
的格式輸夠 \(n\) 個就行了。
點選檢視程式碼
#include<cstdio>
using namespace std;
int main()
{
int T; scanf("%d",&T);
while(T--)
{
int n; scanf("%d",&n);
if(n&1) printf("NO\n");
else
{
printf("YES\n");
for(int i=1;i<=n>>1;i++)
{
char ch='A'+(i&1);
putchar(ch),putchar(ch);
}
putchar('\n');
}
}
return 0;
}
B. Array Fix
利用貪心,讓前面的數拆的儘量小,所以只要可以拆(十位大於個位且拆開後比前面打)就直接拆,最後判斷是不是不降序列。
點選檢視程式碼
#include<cstdio>
using namespace std;
const int N=55;
int n,a[N];
int m,b[N<<1];
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
m=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]<10) b[++m]=a[i];
else
{
if(a[i]/10>=b[m] && a[i]/10<=a[i]%10)
{
b[++m]=a[i]/10;
b[++m]=a[i]%10;
}
else b[++m]=a[i];
}
}
bool ans=true;
for(int i=2;i<=m;i++)
if(b[i]<b[i-1])
{
ans=false;
break;
}
printf("%s\n",ans?"YES":"NO");
}
return 0;
}
C. Arrow Path
類似圖遍歷的處理方法,記錄每一個位置能否透過第一/二步到達,然後轉換步驟嘗試再走。
最後判斷終點是否能以第二步到達。
點選檢視程式碼
#include<cstdio>
#include<queue>
using namespace std;
const int N=2e5+5;
int n;
char str[5][N];
bool arrow[5][N];
bool f[5][N],g[5][N]; //can reach there by step 1/2
const int dx[5]={1,-1,0,0};
const int dy[5]={0,0,1,-1};
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%s%s",&n,str[1]+1,str[2]+1);
for(int i=1;i<=n;i++)
{
f[1][i]=f[2][i]=g[1][i]=g[2][i]=false;
arrow[1][i]=str[1][i]=='>';
arrow[2][i]=str[2][i]=='>';
//0-'<'; 1-'>'
}
queue<pair<pair<int,int>,bool>> q;
q.push({{1,1},0});
while(!q.empty())
{
int x=q.front().first.first,y=q.front().first.second;
bool type=q.front().second;
q.pop();
if(type==0) //to go step1
{
for(int i=0;i<4;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(tx>=1&&tx<=2 && ty>=1&&ty<=n && !f[tx][ty])
{
f[tx][ty]=true;
q.push({{tx,ty},1});
}
}
}
if(type==1) //to go step2
{
int tx=x,ty=y;
if(arrow[x][y]) ty++;
else ty--;
if(tx>=1&&tx<=2 && ty>=1&&ty<=n && !g[tx][ty])
{
g[tx][ty]=true;
q.push({{tx,ty},0});
}
}
}
printf("%s\n",g[2][n]?"YES":"NO");
}
return 0;
}
D. Tandem Repeats?
如果我告訴你我是用暴力 \(O(N^3)\) 卡過的你信嗎?
就是列舉兩段序列開頭,然後暴力判斷是否合法。
然後剪枝 + 各種反轉搜尋順序 + 猜測 Hack 資料就稀裡糊塗卡過了(\(1609\) ms)
不建議學,可以去看下正解。
點選檢視程式碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5005;
int n; char s[N];
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
n=strlen(s+1);
int ans=0;
for(int l1=1;l1<=n&&l1<=n-(ans<<1);l1++)
{
// if(ans>=(n-l1+1)>>1) break;
for(int l2=l1+((n-l1+1)>>1);l2>l1&&l2>ans+l1;l2--)
{
// if(ans>=l2-l1) break;
bool flag=true;
for(int len=l2-l1;len>=1;len--)
{
int p1=l1+len-1,p2=l2+len-1;
if(!(s[p1]=='?'||s[p2]=='?' || s[p1]==s[p2]))
{flag=false; break;}
}
if(flag) ans=max(ans,l2-l1);
}
}
printf("%d\n",ans<<1);
}
return 0;
}
E. Clique Partition
正在施工……