复习
前言
昨天的题比较难。我还不是很理解,主要是个别代码,感觉比较难理解。我再学一遍。今天把周一的题再写一遍,感觉周一的题应该还是比较理解的,就是并查集。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1e5+10;
int p[N];
int find(int x){
if(x!=p[x]){
p[x]=find(p[x]);
}
return p[x];
}
int main(){
for(int i=1;i<N;i++){
p[i]=i;
}
int n;
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
x=find(x);
cout<<x<<" ";
p[x]=x+1;
}
return 0;
}
能比较顺畅地写出来。周二的题现在更懂一些了。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
vector<int> a[N];
int f[4][N];
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
int x;
cin>>x;
a[x%m].push_back(x);
}
memset(f,-0x3f,sizeof f);//取最大值,最开始取成负数,按道理说取成-1也行,有点奇怪了
f[0][0]=0;//上面的取成 -1 竟然不行
for(int i=0;i<m;i++){
sort(a[i].begin(),a[i].end());
reverse(a[i].begin(),a[i].end());//相当于从大到小排序,贪心的做法
for(int u=0;u<3&&u<a[i].size();u++){//选择的是最大的三个余数
int x=a[i][u];//当前选择的数字
for(int j=3;j>=1;j--){//选择三个数字
for(int k=0;k<m;k++){//属性是最大值
f[j][k]=max(f[j][k],f[j-1][(k-x%m+m)%m]+x);//状态转移方程
}//j 表示的是选择数字的个数,k 表示的是当前和模除m的余数
}
}
}
cout<<f[3][0]<<endl;
return 0;
}
刚看到那道题太难了,我还是先做一些简单一些的题,做难题性价比太低了一些,我可能也学不会。判断难度的话,只要超过半个小时的视频讲解的那种,我现阶段直接放弃。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=10010,M=N*2;
int n,m;
int h[N],e[M],w[M],ne[M],idx;
int dist[N];
int p[N];
int res[M*2];
int st[N];
vector<PII> query[N];
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u ,int fa){
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa){
continue;
}
dist[j]=dist[u]+w[i];
dfs(j,u);
}
}
int find(int x){
if(x!=p[x]){
p[x]=find(p[x]);
}
return p[x];//现在唯一比较熟练的模板。
}
void tarjan(int u){
st[u]=1;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!st[j]){
tarjan(j);
p[j]=u;
}
}
for(auto item:query[u]){
int y=item.first,id=item.second;
if(st[y]==2){
int anc=find(y);
res[id]=dist[u]+dist[y]-2*dist[anc];
}
}
st[u]=2;
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
if(a!=b){
query[a].push_back({b,i});
query[b].push_back({a,i});
}
}
for(int i=1;i<=n;i++){
p[i]=i;
}
dfs(1,-1);
tarjan(1);
for(int i=0;i<m;i++){
cout<<res[i]<<endl;
}
return 0;
}
思路
思路还是比较简单的,就是要实现一堆图论的模板函数。这个可能就是熟能生巧。什么并查集,tarjan , dfs
,都是我不熟练的模板,还有链表。之前有一些可能还是比较熟练的,现在完全不熟练了。今天去健身也是狠狠上大重量,其实我们做很多东西都是要熟练度。多练习。
现在自己练习了很长一段时间盲打了,但是敲代码还是不行,因为涉及到一些什么尖括号,井号,括号,还有大小写什么的,比较难受,期待自己快速准确盲打的那一天,希望能坚持坚持。练习盲打还有点上瘾,可能可以帮助逃避压力。
在浏览器里面快捷键切换页面是 ctrl + tab
和 ctrl +shift +tab
今天没有复习算法设计与分析,这个差点也写不了,我们总会因为各种原因坚持不下来,可以理解。今天走了两万多步,也是非常充实。