Preface
重點策略:
\[\large\textbf{\underline{先寫簡單好寫的演算法,再逐步修改最佳化}}
\]
十分有效,百試百靈,屢試不爽。
A. Binary Imbalance
當有相鄰兩字元不相等時,就可以不斷向中間插入 0
。
所以輸出 NO
當且字串全為 1
。
點選檢視程式碼
#include<cstdio>
using namespace std;
const int N=105;
int n;
char str[N];
bool check()
{
for(int i=1;i<n;i++)
if((str[i]-'0')^(str[i+1]-'0'))
return true;
if(str[1]=='0') return true;
else return false;
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%s",&n,str+1);
printf("%s\n",check()?"YES":"NO");
}
}
B. Getting Points
究極橙題。
做法有點像這篇題解,用的是 \(O(1)\) 的數學做法。但是如果讓我再來一次,我寧願用二分。
因為數學做法太容易掛了,而且腦子要燒爛,看下程式碼就知道了。
下次遇到這種題先打最不容易錯的,再逐步最佳化(這題甚至不用最佳化)。
點選檢視程式碼
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
long long n,p,l,t;
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld%lld",&n,&p,&l,&t);
long long week=ceil(n/7.0);
if((week+1)/2*l+week*t>=p) printf("%lld\n",n-min((long long)ceil(1.0*p/(l+t*2)),week));
else printf("%lld\n",n-(week+1)/2-(long long)ceil(1.0*(p-(week+1)/2*l+week*t)/l));
}
return 0;
}
C. Insert and Equalize
所選 \(x\) 為 \(\gcd(a_1,a_2,\dots,a_n)\),排序後如果原序列是等差數列就把 \(a_{n+1}\) 放在開頭或末尾,否則在中間找一個值最大的空插進去。
最後序列要全部變為最大值,用最大值減每一個數再除以最大公約數就是每一次的操作次數,全部加起來即可。
點選檢視程式碼
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e5+5;
int n;
long long a[N];
int gcd(int x,int y){return y?gcd(y,x%y):x;}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
if(n==1)
{
printf("1\n");
continue;
}
sort(a+1,a+n+1);
int d=a[2]-a[1];
for(int i=2;i<n;i++)
d=gcd(d,a[i+1]-a[i]);
long long ans=0;
for(int i=1;i<=n;i++)
ans+=(a[n]-a[i])/d;
bool is_full=true;
for(int i=n;i>=2;i--)
if(a[i]-a[i-1]!=d)
{
ans+=(a[n]-(a[i]-d))/d;
is_full=false;
break;
}
if(is_full) ans+=min((long long)(a[n]-(a[1]-d))/d,1ll*n*d);
printf("%lld\n",ans);
}
return 0;
}
D. Robot Queries
這題做的挺順的,就是連著被卡空間又被卡時間有點不爽。
但是做這道題就是“先寫簡單好寫的寫法,再逐步最佳化”策略的典範,以後要多多按照這個策略做題。
我的洛谷題解
E. Collapsing Strings
看出來是字典樹,也有一些做法,但是實現比較複雜還容易錯,所以我用的是這篇題解的處理方法。
久了沒打字典樹都快忘了,這次正好複習一下。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+5;
int n;
string str[N];
long long ans,sumlen;
namespace Trie{
int trie[N][30],idx;
int cnt[N],end[N];
void insert(string &s)
{
int p=0;
for(int i=0;i<(int)s.length();i++)
{
int num=s[i]-'a'+1;
if(!trie[p][num]) trie[p][num]=++idx;
p=trie[p][num];
cnt[p]++;
}
end[p]++;
return;
}
long long query(string &s)
{
int p=0;
long long res=1ll*s.length()*n+sumlen;
for(int i=0;i<(int)s.length();i++)
{
int num=s[i]-'a'+1;
if(trie[p][num])
{
p=trie[p][num];
res-=2*cnt[p];
}
else break;
}
return res;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>str[i];
sumlen+=str[i].length();
Trie::insert(str[i]);
}
for(int i=1;i<=n;i++)
{
reverse(str[i].begin(),str[i].end());
ans+=Trie::query(str[i]);
}
printf("%lld\n",ans);
return 0;
}