D-我不是大富翁
題意:
做法:一開始是往貪心方面想,但是很明顯,貪不了。又因為走的步先後順序沒影響,可以用dp來寫。暴力也差不多。
值得注意的點是動力序列可以一邊讀入一邊處理,省了點空間。
如果dp[5005][5005]這樣開的話會MLE,實際上在dp的過程中,用到的只是i和i-1兩行,其餘都是多餘的。
所以可以這樣定義dp[2][5005]這樣可以避免MLE;
還有就是要特判n==1的情況。
//int dp[5005][5005]; //--MLE
int dp[2][5005]; //最佳化空間!!! wa--5 1 0
//dp[i][j]定義為,到了第i步,可以到達j哪些格子。
//暴力差不多--遍歷m步.每步遍歷n,看看可以到達哪些格子.看看最後一步是否可以到達1.
void solve(){ //D
int n,m,x;
cin>>n>>m;
if(n==1){ //特判!!
cout<<"YES";
return;
}
dp[0][1]=1;
for(int i=1;i<=m;i++){
cin>>x;
x%=n;
for(int j=1;j<=n;j++){
if(dp[(i+1)%2][j]){
dp[(i+1)%2][j]=0; //重置!!!否則下一步會再次進入
dp[i%2][(j+x)%n]=1;
dp[i%2][(j-x+n)%n]=1;
}
}
}
if(dp[m%2][1]) cout<<"YES";
else cout<<"NO";
}
在寫的時候加了個條件判斷x==0的情況,但是實際上x==0的情況是相同處理的,不用特別處理。
E-多重對映
題意:
做法有兩種。
法一:順著做,並查集(維護集合的關係,不是值的關係),加一點其他輔助。設定兩個unordered_map<int,int>:mp1[集合]=值 ,mp2[值]=集合。
int fa[1000006]; //fa存的是各個集合,不是值!!
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void Union(int x,int y){
int fa1=find(x),fa2=find(y);
fa[fa1]=fa2;
}
//這題順著做,對映關係有點繞,要想清楚對映關係!!
void solve(){ //E多重對映--①多重對映 or ②正難則反 有T=1e5組樣例,ai最大又有1e6。如果每個樣例都初始化到1e6--TLE--solve--輸入哪個數字初始化哪個數字。
int n,m,arr[100005];
cin>>n>>m;
map<int,int> mp1,mp2; //key!! mp1[集合]=值 : mp2[值]=集合
for(int i=1;i<=n;i++){
cin>>arr[i];
fa[arr[i]]=arr[i];
mp1[arr[i]]=arr[i];
mp2[arr[i]]=arr[i];
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
if(!mp2[x]||x==y) continue; //x不存在於集合
if(!mp2[y]){ //如果y不存在於集合
mp2[y]=mp2[x]; //y存在於x的集合
mp1[mp2[x]]=y; //x的集合對應的值為y
mp2.erase(x); //刪除x,x不存在於集合
}
else{
Union(mp2[x],mp2[y]); //集合的Union!!
//x集合已經融入到y集合,所以要先刪除x集合對應的值,並且刪除x集合。
mp1.erase(mp2[x]);
mp2.erase(x);
}
}
for(int i=1;i<=n;i++) cout<<mp1[find(arr[i])]<<" ";
cout<<endl;
}
法二:巧妙,正難則反。倒著遍歷操作。
int fa[1000006];
void solve(){ //E-法二-正難則反
int n,m,arr[100005];
cin>>n>>m;
for(int i=1;i<=n;i++) {
cin>>arr[i];
fa[arr[i]]=arr[i]; //!!!
}
vector<pair<int,int>> vct;
for(int i=1;i<=m;i++){
pair<int,int> x;
cin>>x.first>>x.second;
vct.emplace_back(x);
fa[x.first]=x.first; //!!!所有出現的數字都要初始化為自己
fa[x.second]=x.second;
}
for(int i=m-1;i>=0;i--){
auto [x,y]=vct[i];
fa[x]=fa[y]; //!!!!!!
}
for(int i=1;i<=n;i++){
cout<<fa[arr[i]]<<" ";
}
cout<<endl;
}
妙