C Cover the Tree
题目传送门
题目大意
给定一个无根树,求最小链数去覆盖书上所有的边。输出最小数字和其中任何一个解决方案
思路
很显然要去找到所有的叶结点并且将其覆盖,所以先找到一个非叶结点,从此结点出发去寻找其他的叶节点,偶数直接输出结点个数的一半即为最小链数,奇数则向上取整
AC Code
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
// #define TDS_ACM_LOCAL
const int N=2e5 +9;
int n, u, v;
int b[N], cnt;
vector<int> a[N];
void dfs(int u, int fa){ //u为当前结点,fa为父节点
if(a[u].size()==1) {b[++cnt]=u; return ;} //如果为叶结点就存下来
for(auto v: a[u]){
if(v==fa) continue; //如果为父节点则跳过
dfs(v,u);
}
return ;
}
void solve(){
cin>>n;
for(int i=1; i<=n-1; i++){
cin>>u>>v;
a[u].push_back(v), a[v].push_back(u);
}
int root=1;
while(a[root].size()==1) root++; //找到一个不为叶结点的结点,作为dfs的起点
dfs(root,-1);
cout<<(cnt+1)/2<<endl;
for(int i=1; i<=cnt/2; i++){
cout<<b[i]<<" "<<b[cnt/2+i]<<endl;
}
if(cnt&1) cout<<b[1]<<" "<<b[cnt]<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
solve();
return 0;
}
D Duration
题目传送门
思路
显然
AC Code
#include<cstdio>
#include<iostream>
#include<math.h>
using namespace std;
// #define TDS_ACM_LOCAL
int fun(string a){
return ((a[0]-'0')*10+(a[1]-'0'))*3600 +((a[3]-'0')*10+(a[4]-'0'))*60 +((a[6]-'0')*10+(a[7]-'0'));
}
string a, b;
void solve(){
cin>>a>>b;
cout<<fabs(fun(a)-fun(b))<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
solve();
return 0;
}
F Fake Maxpooling
题目传送门
思路
直接暴力的话复杂度会很高,所以可以采取单调队列维护区间最大值
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
// #define TDS_ACM_LOCAL
const int N=5009;
int n, m ,k;
int a[N][N], b[N][N];
deque<int> q;
inline int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void solve(){
memset(b, 0, sizeof(b));
cin>>n>>m>>k;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
a[i][j]=i*j/gcd(i, j);
for(int i=1; i<=n; i++){
q.clear();
for(int j=1; j<=m; j++){
while(!q.empty() && q.front()<=j-k) q.pop_front(); //维护的是一个区间,我们只关注最大值的下标
while(!q.empty() && a[i][q.back()]<=a[i][j]) q.pop_back(); //更新队列(新进入的值从队尾开始删除不大于它的值
q.push_back(j);
b[i][j]=max(b[i][j], a[i][q.front()]); //将维护的区间的最大值存到b中
}
}
long long ans=0;
for(int i=k; i<=m; i++){
q.clear();
for(int j=1; j<=n; j++){
while(!q.empty() && q.front()<=j-k) q.pop_front();
while(!q.empty() && b[q.back()][i]<= b[j][i]) q.pop_back();
q.push_back(j);
if(j>=k) ans+=b[q.front()][i]; //注意前k-1列无法形成k*k的子矩阵的
}
}
cout<<ans<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
solve();
return 0;
}