2020牛客暑期多校训练营(第二场)C、D、F

发布于 2020-08-05  0 次阅读


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

思路:

直接暴力的话复杂度会很高,所以可以采取单调队列维护区间最大值

AC Code:

#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;
}


平平无奇的在校大学生