codeforce 1400 加 树形dp 板子

文章讨论了在Codeforces竞赛中的两个问题,涉及操作优化、数组操作策略以及深度优先搜索(DFS)在计算节点深度和节点关系中的应用。作者解析了如何在给定条件下最小化操作次数,以及利用模板简化复杂问题求解。
摘要由CSDN通过智能技术生成

Problem - D1 - Codeforces

题目保证y <= x 

因为 y  <= x 所以尽量不操作相邻的数,只有当a ,b 只有两个不相同的数时,将这两个数变为相同,需要 两次 y 操作,如果这两个数正好相邻 那么需要一次x操作,则需要比较一下 代价,

min(x , 2 * y); 对于其他情况都可以转换为 y 操作。

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int N = 2e5 + 10;
int t;
int num[N];

void solve()
{
    int n,x,y;cin >> n >> x >> y;
    string a,b;cin >> a >> b;
    int cnt = 0;
    for(int i = 0;i < n;i ++)
    {
        if(a[i] != b[i])num[++ cnt] = i;
    }
    if(cnt % 2){cout << "-1" << endl;return ;}
    if(cnt == 0){cout << "0" << endl;return ;}
    if(cnt == 2){
        if(num[1] + 1 == num[2]){
            cout << min(x , 2 * y) << endl;
        }
        else cout << y << endl;
    }
    else {
        cout << cnt * y / 2 << endl;
    }
    
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> t;
    while(t --)solve();
    return 0;
}

Problem - 1697C - Codeforces

对于两种操作,每次都将a向后移动,将c向前启动,a,c的相对位置不会改变。

所以我们不需要考虑b的位置,将b全部删去,考虑a,c的相对位置即可。

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int N = 2e5 + 10;
int t;
void solve()
{
    int n;cin >> n;
    string a,b;cin >> a >> b;
    int cnt2 = 0;
    int cnt1 = 0;
    int j = 0;
    for(int i = 0;i <= n;i ++)
    {
        while(b[j] == 'b')cnt2 ++,j ++;
        if(a[i] == 'b'){cnt1 ++;continue;};
        if(a[i] != b[j] || a[i] == 'a' && i > j || a[i] == 'c' && i < j)
        {
            cout << "NO" << endl;
            return ;
        }
        j ++;
    }
    while(b[j] == 'b')cnt2 ++,j ++;
    if(cnt1 != cnt2)
    {
        cout << "NO" << endl;
        return ;
    }
    cout << "YES" <<endl;
    return ;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> t;
    while(t --)solve();
    return 0;
}

Problem - 1696C - Codeforces

容易发现两个操作本质上是互逆的,因此只要将 a 和 b 中的所有元素拆开再比较是否相同即可。

注意最后的数字总数可能过大,所以将a拆开后,对于b数组一边拆一边比;

大佬代码  

#include<bits/stdc++.h>
#define N 1000005
#define int long long
using namespace std;
int T,n,m,k,a[N],b[N],p1,p2,sum1,sum2;
struct node{
	int num,sum;
};
stack<node>s;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m;
		bool flag=1; 
		sum1=sum2=0;
		while(!s.empty())s.pop();
		for(int i=1;i<=n;i++){
			cin>>a[i],sum1+=a[i];
			int tmp=1;
			while(a[i]%m==0)a[i]/=m,tmp*=m;
			s.push((node){
				a[i],tmp
			});
		}
		cin>>k;
		for(int i=1;i<=k;i++)cin>>b[i],sum2+=b[i];
		if(sum1!=sum2){
			puts("No");
			continue;
		}
		for(int i=k;i>=1;i--){
			int tmp=1;
			while(b[i]%m==0)b[i]/=m,tmp*=m;
			while(tmp){
				if(s.empty()||b[i]!=s.top().num){
					flag=0;
					break;
				}
				if(tmp>=s.top().sum)tmp-=s.top().sum,s.pop();
				else {
					s.top().sum-=tmp;
					tmp=0;
				}
			}
			if(!flag)break;
		}
		puts(flag?"Yes":"No");
	}
} 

P3478 [POI2008] STA-Station - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

换根dp 模板题

暴力做法 dfs 暴力求每个点的深度之和,但是我们发现对于x的节点 我们如果求出它的父节点的深度,x的节点的深度之和可以通过父节点的深度计算出来,

当x为根节点时,x的父节点的所有子节点深度会增加1 ,而x 包含x 的所有子节点深度会减小1;

所以我们第一遍dfs维护每个节点子节点个数siz[N]数组和每个节点的深度dep[N]数组。

第二遍dfs 算出每个节点的深度之和

但是我们最开始的第一个节点需要暴力求出来,这也就是为什么要维护dep[N]数组

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
const int N = 1e6 + 10;
#define int long long
int n,m;
vector<int> tr[N];
int siz[N];
int dep[N];
int f[N];

void dfs(int u,int fa)
{
    siz[u] = 1,dep[u] = dep[fa] + 1;
    for(int v : tr[u])
    {
        if(v != fa){
            dfs(v , u);
            siz[u] += siz[v];
        }
    }
}

void dfs1(int u,int fa)
{
    for(int v : tr[u])
    {
        if(v != fa)
        {
            f[v] = f[u] - siz[v] + n - siz[v];
            dfs1(v , u);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1;i < n;i ++)
    {
        int a,b;cin >> a >> b;
        tr[a].push_back(b);
        tr[b].push_back(a);
    }

    dfs(1 , -1);
    for(int i = 1;i <= n;i ++)f[1] += dep[i];
    dfs1(1 , -1);
    int ans = 0; 
    int id = 0;
    for(int i = 1;i <= n;i ++)if(ans < f[i]){
        ans = f[i],id = i;
    }
    cout << id << endl;
    return 0;
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谁能告诉我未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值