The 2022 ICPC Asia Regionals Online Contest (I)CDH

发布时间 2023-08-22 00:34:43作者: nannan4128

The 2022 ICPC Asia Regionals Online Contest (I)

C Delete the Tree

题意:想要删掉一棵树,你可以做以下两种操作:

  1. 删除:删除一个点以及和它连的边
  2. 收缩:选择一个点\(x\)它直接连有\(2\)个点\(u,v\),我们可以把\(x\)删了,在把\(u,v\)连起来

问你:最少执行删除操作多少次?

思路:要删除次数最少,那我们先尽可能的去收缩。思考一下,一棵树最终会收缩成什么样子?

我们可以把叶子节点的链一直往上收缩,直到收缩不了为止。

反过来考虑,哪些是一定需要删除操作的?只有当是一条链的情况可以收缩,那么,对于一个点,它的度数最多是\(2\),大于\(2\)的部分要删去(只保留它自己往父亲和往儿子连的两条边)。这样的话,树就可以开始收缩了,最终收缩完以后最后一定还要删\(2\)个点(不能再收缩了)。

当然不要忘记特判\(n=1\)的情况,这种情况直接输出\(1\)就ok了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int d[N];
ll ans = 0;

/*
1
6
1 2
1 3
1 4
1 5
1 6
*/
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		if(n==1)
		{
			cout<<1<<"\n";
			continue;
		}
		ans = 0;
		for(int i = 1;i<=n;i++)
			d[i] = 0;
		for(int i = 1;i<n;i++)
		{
			int x,y;
			cin>>x>>y;
			d[x]++,d[y]++;
		}
		// for(int i = 1;i<=n;i++)
		// 	cout<<d[i]<<" ";
		// cout<<endl;
		for(int i = 2;i<=n;i++)
		{
			ans += max(0,d[i]-2);
		}
		ans += 2;
		ans += max(d[1] - 2, 0);
		cout<<ans<<endl;
	}	

	return 0;
}

D Find the Number

题意:一个数\(x\)被认为是好的,当且仅当其二进制末尾\(0\)的个数对于\(1\)的个数。

给你\(l,r\),让你在\([l,r]\)区间内找出好数,没有就输出\(-1\)

思路:我们分类讨论:

  1. \(1\)的个数大于\(0\)的个数,那么我们想要\(0\)的个数变多。如何变多?让它进位。所以我们对当前数加上一个它的\(lowbit\)
  2. \(1\)的个数小于\(0\)的个数,那么我们要要\(1\)的个数变多。对当前数\(+1\)
  3. 如果一样,那就输出

注意以上操作还要保证数在\([l,r]\)之间。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;

int lowbit(int x)
{
	return x&(-x);
}

int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		int l,r;
		cin>>l>>r;
		bool ok = false;
		while(l<=r)
		{
			int cnt0 = __builtin_ctz(l);
			int cnt1 = __builtin_popcount(l);
			if(cnt0==cnt1)
			{
				ok = true;
				break;
			}
			if(cnt0<cnt1)
				l += lowbit(l);
			else l += 1;
 		}
		if(ok)cout<<l<<"\n";
		else cout<<-1<<"\n";
	}
	return 0;
}

H Step Debugging

题意:告诉你几个\(C--\)语法,问你调用了库函数多少次。

思路:

法一:栈模拟。

我们对字符串做以下转化:

  1. \(repeat->(\)
  2. \(librart->1+\)
  3. \(arithemtic->0+\)
  4. 数字\(->*\)数字
  5. \(for->)\)

转化完以后,我们删去没有用的\(+\)号,之后开始做栈模拟计算结果即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
string s[N],t[N],a[N];
int n,m,len;
const int mod = 20220911;
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	while(1)
	{
		string t;
		cin>>t;
		if(t=="fin")break;
		s[++n] = t;
	}

	for(int i = 1;i<=n;i++)
	{
		if(s[i]=="repeat")t[++len]="(";
		if(s[i]=="library")t[++len] ="1",t[++len] = "+";
		if(s[i]=="arithmetic")t[++len] ="0",t[++len] = "+";
		if(isdigit(s[i][0]))t[++len] = "*",t[++len]=s[i],t[++len] = "+";
		if(s[i]=="for")t[++len] = ")";
	}

	for(int i = 1;i<=len;i++)
	{
		if(t[i]=="+")
		{
			if(i+1<=len&&t[i+1]!=")")a[++m] = t[i];
			else{
				 continue;
			}
		}
		else if(isdigit(t[i][0])&&t[i-1]==")"){
			a[++m] = "+",a[++m] = t[i];
		}
		else a[++m] = t[i];
	};
	stack<string>tmp;
	stack<int>ans;

	int i = 1;
	ll ret = 0;
	while(i<=m)
	{
		if(a[i]=="*")
		{
			ll res = ans.top()%mod;
			ans.pop();
			res = res*stoi(a[i+1])%mod;
			tmp.push(to_string(res));
			i++;
		}
		else if(a[i]!=")")
			tmp.push(a[i]);
		else
		{
			int res = 0;
			while(tmp.top()!="(")
			{
				string x = tmp.top();
				//cout<<"x = "<<x<<endl;
				if(isdigit(x[0]))
				{
					
					res += stoi(x);
				}
				tmp.pop();
			}
			if(tmp.top()=="(")
			tmp.pop();
			//cout<<"res = "<<res<<endl;
			ans.push(res);
		}
		i++;
	}
	while(!tmp.empty())
	{
		string x = tmp.top();
		if(isdigit(x[0]))
			ret += stoi(tmp.top()),ret %= mod;
		tmp.pop();
	}
	cout<<ret%mod<<endl;
	return 0;
}

法二:\(dfs\)

#include<bits/stdc++.h>
using namespace std;
const int mod=20220911;
string s;
int res;
int dfs()
{
    string s;
    int res=0;
    while(cin>>s,s!="for")
    {
        if(s=="library")
        {
            res++;
        }
        else if(s=="repeat")
        {
            res+=dfs();        
        }
    }
    int num;
    cin>>num;
    cin>>s;
    return num*res%mod;
}
int main()
{
    cin>>s;
    while(cin>>s,s!="fin")
    {
        if(s=="library")
            res++;
        else if(s=="repeat")
            res+=dfs();
    }
    cout<<res%mod<<"\n";
    return 0;
}

A 01 Sequence