這場比賽由於急躁心態不穩導致abc三題接連wa,這時候心態幾乎爆炸。而d題思路其實很清晰,但是因為set使用不熟練卡住。最後沒用set十分鐘就寫完過了。這時候只剩下十多分鐘來不及寫別的了。結束
收穫主要就是:還是要注意邊界的細節(
ab題就不放了。。
C - Rudolf and the Ugly String
這題具體是個什麼咱也不知道。反正就是字串匹配。就是沒有什麼演算法硬做,只有三種情況
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int a[maxn];
signed main()
{
// int t=read();
int t;
cin>>t;
while(t--){
int n;
string s;
cin>>n>>s;
int j=0;
int k=0;
int ans=0;
for(int i=0;i<n;i++){
if(!j&&s[i]=='m'){
k=0;
j++;
}
else if(j==1&&s[i]=='a'){
k=0;j++;
}
else if(j==2&&s[i]=='p'){
j=0;k=0;ans++;
}
else if(!k&&s[i]=='p'){
j=0;k++;
}
else if(k==1&&s[i]=='i'){
j=0;k++;
}
else if(k==2&&s[i]=='e'){
k=0;ans++;
}
}
cout<<ans<<endl;
}
}
D - Rudolf and the Ball Game
這題只有前一個狀態和現在的狀態有用,本來用set想去重的,但是直接替換成遍歷用01表示了(因為n不是很大可以每次都遍歷
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+5;
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int a[maxn][2];
signed main()
{
int t,n,m,x,dis;
cin>>t;
while(t--){
cin>>n>>m>>x;
for(int i=1;i<=n;i++){
a[i][0]=0;
a[i][1]=0;
}
int pos=0;
a[x][0]=1;
for(int i=1;i<=m;i++){
pos=pos^1;
cin>>dis;
char c;
cin>>c;
if(c=='0'){
for(int i=1;i<=n;i++){
if(a[i][pos^1]){
int p=(dis+i)%n;
if(!p)p=n;
a[p][pos]=1;
a[i][pos^1]=0;
}
}
}
else if(c=='1'){
for(int i=1;i<=n;i++){
if(a[i][pos^1]){
int p=(i+n-dis)%n;
if(!p)p=n;
a[p][pos]=1;
a[i][pos^1]=0;
}
}
}
else{
for(int i=1;i<=n;i++){
if(a[i][pos^1]){
int p=(dis+i)%n;
if(!p)p=n;
a[p][pos]=1;
p=(i+n-dis)%n;
if(!p)p=n;
a[p][pos]=1;
a[i][pos^1]=0;
}
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(a[i][pos])ans++;
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)
if(a[i][pos])cout<<i<<' ';
cout<<endl;
}
}
E - Rudolf and k Bridges
這個也不難吧。。單調佇列滑窗
個人寫滑窗的習慣是到了從能有答案的地方開始算然後把前面的放進去
#include<bits/stdc++.h>
#define ls (p<<1)
#define int long long
using namespace std;
const int maxn=105;
const int inf=1e17;
int read(){
int ret=0,f=1;char c=getchar();
while(c<'0'||c>'9') if(c=='-')f=-1,c=getchar();
while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
return ret*f;
}
int read(int a[]){
char c=getchar();
int j=0;
while((c<'0')||(c>'9'&&c<'A')||(c>'Z'&&c<'a')||c>'z') c=getchar();
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9'))
a[++j]=c-'a'+1,c=getchar();
return j;
}
int cs[maxn];
deque<int>mn;
deque<int>mnn;
signed main(){
int t=read();
while(t--){
int n=read(),m=read(),k=read(),d=read();
int ans=inf,sum=0;
d+=1;
for(int i=1;i<=n;i++){
int b=0;cs[i]=inf;
for(int j=1;j<=m;j++){
int v=read();
if(j==1){
b=1;
continue;
}
while(!mnn.empty()&&(mnn.front()<(j-d)))
mnn.pop_front(),mn.pop_front();
while(!mn.empty()&&mn.back()>b)
mnn.pop_back(),mn.pop_back();
mnn.push_back(j-1),mn.push_back(b);
v=mn.front()+v+1;
// cout<<j<<' '<<v<<endl;
b=v;
if(j>=m-d&&j<m){
cs[i]=min(cs[i],v+1);
}
else if(j==m){
cs[i]=min(cs[i],v);
}
}
// cout<<cs[i]<<endl;cout<<endl;
sum+=cs[i];
if(i>=k){
sum-=cs[i-k];
ans=min(ans,sum);
}
}
cout<<ans<<endl;
}
}
F - Rudolf and Imbalance
這個題嘞。。我一開始也是想分類討論就是因為我是想直接二分找接近pmx的答案的。後面我觀察了dalao的做法發現可以直接二分找中值(最佳值)在和pmx比較。。
不過就是因為中值不能確定一個最佳值,所以不能直接縮小到mid,要縮小到l=r-1然後把l和r都比較來找最佳值,這邊我debug搞了很久一開始是直接用mid()
#include<bits/stdc++.h>
#define ls (p<<1)
#define int long long
using namespace std;
const int maxn=2e5+5;
int read(){
int ret=0,f=1;char c=getchar();
while(c<'0'||c>'9') if(c=='-')f=-1,c=getchar();
while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
return ret*f;
}
int read(int a[]){
char c=getchar();
int j=0;
while((c<'0')||(c>'9'&&c<'A')||(c>'Z'&&c<'a')||c>'z') c=getchar();
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9'))
a[++j]=c-'a'+1,c=getchar();
return j;
}
int a[maxn],f[maxn],d[maxn];
signed main(){
int t=read();
while(t--){
int mk=0;
int n=read(),m=read(),k=read();
int mx=0,pmx=0;
for(int i=1;i<=n;i++){
a[i]=read();
if(i==1)continue;
if(mx<=(a[i]-a[i-1])){
pmx=mx;
mx=a[i]-a[i-1];
mk=i-1;
}
}
for(int i=1;i<=m;i++)d[i]=read();
sort(d+1,d+m+1);
for(int i=1;i<=k;i++)f[i]=read();
if(pmx==mx){
cout<<mx<<endl;
continue;
}
for(int i=1;i<=n-1;i++){
if(a[i+1]-a[i]!=mx)pmx=max(a[i+1]-a[i],pmx);
}
int lw=a[mk+1]-pmx,hi=a[mk]+pmx;
int ans=mx;
// cout<<pmx<<' '<<mx<<"okok"<<endl;
for(int i=1;i<=k;i++)
{
int l=1,r=m,mid=(l+r)>>1;
int qub=(a[mk+1]+a[mk])/2;
if((a[mk+1]+a[mk])%2)qub++;
while(l+1<r){
mid=(l+r)>>1;
if(f[i]+d[mid]<qub)l=mid;
else r=mid;
}
int q1=f[i]+d[r]-a[mk],q2=a[mk+1]-f[i]-d[r];
ans=min(ans,max(q1,q2));
q1=f[i]+d[l]-a[mk],q2=a[mk+1]-f[i]-d[l];
ans=min(ans,max(q1,q2));
}
ans=max(pmx,ans);
cout<<ans<<endl;
}
}
G - Rudolf and Subway
這個題我不會啊。看題解的。
重新建圖思路很巧妙。不過現在也知道了看到這種沒辦法直接搜尋的圖,肯定是要想辦法重新建圖的。
老規矩做題先看樣例會發現就算是同一條地鐵線路也是要乘車的。。。(除非是同一個點哈)
然後建圖方法就是把顏色和地鐵站直接連邊,不管地鐵站之間的關係。這樣子每個地鐵站到不同顏色地鐵站的的距離固定是二,最後除以2即可
又因為採用的是廣搜,逐層遍歷,所以搜到的路徑一定是最短路()
#include<bits/stdc++.h>
using namespace std;
#define fir first
#define scd second
const int maxn=2e6+5;
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
signed main()
{
int t=read();
while(t--){
int n=read(),m=read();
vector<pair<int,int> >eg[n+5];
int idx=n+1;
map<int,int>mp;
for(int i=1;i<=m;i++){
int u=read(),v=read(),col=read();
if(mp[col]==0){
mp[col]=idx;
idx++;
}
eg[u].push_back({v,mp[col]});
eg[v].push_back({u,mp[col]});
}
vector<int>edg[idx+5];
for(int i=1;i<=n;i++){
for(int j=0;j<eg[i].size();j++){
int c=eg[i][j].scd,v=eg[i][j].fir;
edg[c].push_back(i);
edg[i].push_back(c);
edg[c].push_back(v);
edg[v].push_back(c);
}
}
int s=read(),t=read();
// cout<<s<<t<<"okok"<<endl;
if(s==t){
cout<<0<<endl;
continue;
}
vector<int> d(idx+5,0);
vector<int> vis(idx+5,0);
queue<int>q;
q.push(s);vis[s]=1;d[s]=0;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<edg[u].size();i++){
if(!vis[edg[u][i]]){
q.push(edg[u][i]);
d[edg[u][i]]=d[u]+1;
vis[edg[u][i]]=1;
}
}
}
if(!d[t])cout<<"-1"<<endl;
else cout<<d[t]/2<<endl;
}
}