2020ICPC·小米 網路選拔賽第一場
阿新 • • 發佈:2020-10-26
2020ICPC·小米 網路選拔賽第一場
比賽分析
這場高手真的還是挺多的。我們隊伍也實在是太拉垮了,有個隊友實驗未歸。
我上來切了C、I 然後就沒有過題了。
首先是J題,我的鍋。我就想了幾分鐘就感覺是二維線段樹,就直接開始寫了,浪費快2hrs+,後來我突然發現我的複雜度少乘了個log,血虧。
隊友的A也調了很久,一直沒有過,據他所說,他被卡傻了。
隊友2終於實驗回來,做了個D,正解應該是邊雙還是啥的,反正他寫個什麼割點啥的。
總結:
這場反正也進不了,但是暴露的問題非常多
第一,各自蠻幹非常明顯,交流少了。 有想法應該先和隊友交流一下,尤其是這種網路賽,多執行緒可敲的時候,反而不要忽視單機子的這個重要流程。像我的二維線段樹,如果講清楚,隊友,或者我自己都可能看到問題,簡單的dp就不會做成資料結構題
第二,題意方面。每個人優先讀一道題,然後翻譯成中文,再讓隊友帶著中文去再讀一遍題意,檢查是否理解錯誤。比如I題,我一開始讀錯了,隊友準備寫的時候,提醒了一下我,我才發現錯誤。以後要保證每道題目至少要被反覆讀過兩遍。
第三,要注意看榜單資訊。如果有些題很多隊過了,或者說,一些題很快被切了,那麼它極大概率不是比較複雜的資料結構題,以及難的數論。。。
第四,是勤換思路。有些時候想題目不要侷限於一種演算法中,要果敢放棄。思路或者題目什麼時候該進行捨棄嘞?
如果思路想不通到15min,並且此題可做,那麼換思路
如果某個題花費30min思考沒有突破,先放下,去讀題
C 簡單簽到
#include<iostream> #include<cstring> #include<cstdio> #include<string> using namespace std; #define INF 0x3f3f3f3f #define max(a,b) (a>b ? a:b) #define min(a,b) (a<b ? a:b) #define swap(a,b) (a^=b^=a^=b) #define maxn 105 #define minn -105 #define ll long long int #define ull unsigned long long int #define uint unsigned int inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'|ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } int main() { string s; cin>>s; int ans=0; int len=s.size(); for(int i=0;i<len;i++) { if(s[i]=='w')ans++; if(i) { if((s[i]=='w')&&(s[i-1]=='w'))ans++; } } cout<<ans<<endl; return 0; }
I dfs 記憶化
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define INF 0x3f3f3f3f #define max(a,b) (a>b ? a:b) #define min(a,b) (a<b ? a:b) #define swap(a,b) (a^=b^=a^=b) #define maxn 1405 #define minn -105 #define ll long long int #define ull unsigned long long int #define uint unsigned int inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'|ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } int n,m; char a[maxn][maxn]; bool been[maxn][maxn]; int out[maxn][maxn]; bool dfs(int x,int y) { if(x==0||y==0||x==n+1||y==m+1) { return 1; } if(been[x][y]) { return out[x][y]; } been[x][y]=1; bool cur=0; if(a[x][y]=='W')cur=dfs(x-1,y); if(a[x][y]=='A')cur=dfs(x,y-1); if(a[x][y]=='S')cur=dfs(x+1,y); if(a[x][y]=='D')cur=dfs(x,y+1); out[x][y]=cur; return cur; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>a[i][j]; } int ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(!been[i][j]) { dfs(i,j); } if(out[i][j]==1)ans++; } cout<<ans<<endl; return 0; }
J dp
維護二維字首和就好了,沒必要實現每次區間的維護。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define max(a,b) (a>b ? a:b)
#define min(a,b) (a<b ? a:b)
#define swap(a,b) (a^=b^=a^=b)
#define maxn 1305
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
inline int read()
{
int ans=0;
char last=' ',ch=getchar();
while(ch<'0'|ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
int a[maxn][maxn];
int pre[maxn][maxn];
int give[maxn][maxn];
int n,m,x,y;
string ac="^_^\n";
string wa="QAQ\n";
void solve()
{
cin>>n>>m>>x>>y;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
a[i][j]=read();
}
int cur=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
//give[i][j]=0;
int cur=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];
pre[i][j]=cur;
cur+=pre[max(0,i-x)][max(0,j-y)]-pre[i][max(0,j-y)]-pre[max(0,i-x)][j];
if(i>=n+2-x||j>=m+2-y)
{
if(a[i][j]!=cur)
{
cout<<wa;
return;
}
continue;
}
else
{
if(cur>a[i][j])
{
cout<<wa;
return;
}
pre[i][j]+=a[i][j]-cur;
}
}
cout<<ac;
}
int main()
{
int _t;
cin>>_t;
while(_t--)solve();
return 0;
}
D
#include<bits/stdc++.h>
using namespace std;
struct tedge{
int w,next;
}e[1000010];
int l[500010],dfn[500010],low[500010],st[500010],del[500010],gu[500010],d[500010];
int cnt,tot,top,cnt1,n,m,root,sum;
vector <int> ve[500010];
void add(int x,int y)
{
e[++cnt].w=y;
e[cnt].next=l[x];
l[x]=cnt;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
st[++top]=x;
if(x==root&&l[x]==0)
{
ve[++cnt1].push_back(x);
gu[x]=1;
return;
}
for(int i=l[x];i;i=e[i].next)
{
int v=e[i].w;
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
if(low[v]>=dfn[x])
{
cnt1++;
int z;
do{
z=st[top--];
ve[cnt1].push_back(z);
}while(z!=v);
ve[cnt1].push_back(x);
}
}
else
low[x]=min(low[x],dfn[v]);
}
}
int main()
{
cin>>n>>m;
int x,y;
for(int i=1;i<=m;i++)
{
cin>>x>>y;
if(x==y)
continue;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
{
sum++;
root=i;
tarjan(i);
}
for(int i=1;i<=cnt1;i++)
for(int j=0; j<ve[i].size();j++)
d[ve[i][j]]++;
for(int i=1;i<=n;i++)
{
if(gu[i])
cout<<sum-1<<" ";
else
cout<<sum-1+d[i]<<" ";
}
return 0;
}
A
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int a[300010],n,m,x;
int f[10000010],bj[10000010],prime[10000100],tot,f1[10000010];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f1[a[i]]++;
f[a[i]]++;
}
sort(a+1,a+n+1);
int maxn=a[n];
int ans=0;
for(int j=2;j<=maxn;j++)
{
if(!bj[j]){
prime[++tot]=j;f[j]+=f[1];
}
for(int i=1;i<=tot;i++)
{
if(j*prime[i]<=maxn)
{
bj[j*prime[i]]=1;
f[j*prime[i]]=max(f[j*prime[i]],f1[j*prime[i]]+max(f[j],f[prime[i]]));
}
else break;
}
ans=max(ans,f[j]);
}
cout<<ans;
return 0;
}