The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou)D、J、M题题解

本文介绍了三道C++编程题目,涉及操作符优先级判断、MysteriousTree(树形结构中的特殊路径查找)以及V-Diagram(计算区间和的优化问题)。通过分析算法和代码,探讨了如何处理输入输出和优化计算过程。

D题Operator Precedence

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        if(n==3){//n为3时要特判,因为n-3为0
            cout<<1<<" "<<-10<<" "<<6<<" "<<6<<" "<<-10<<" "<<1<<endl;
            continue;
        }
        cout<<n*(-1)+3<<" ";
        for(int i=1;i<=n-1;i++){
            cout<<-1<<" "<<2<<" ";
        }
        cout<<1<<endl;
    }
    system("pause");
    return 0;
}

 M题Mysterious Tree

 

 

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int edge(int a,int b){
	cout<<"? "<<a<<" "<<b<<endl;
	cout<<endl;
	int x;
	cin>>x;
	return x;
}
void solve(){
	int n;
	cin>>n;
	int pos=-1;
		for(int i=1;i<=n-1;i+=2){
			int x=edge(i,i+1);
			if(x==1){//检查每两个之间是否相连(由n/2想到),如果都不相连说明是一个链
				pos=i;
				break;
			}
		}
		//要特判最后两个值,因为总数可能为奇数
		if(pos==-1&& n&1 ){
			int x=edge(n-1,n);
			if(x==1) pos=n-1;
		}
		if(pos==-1){
			cout<<"! 1"<<endl;
			cout<<endl;
			return ;
		}
		if(pos!=1){
			//pos为1时情况特殊要排除,可以先考虑不为1时
			//不为1时,我们先观察pos这个点能否成链
			int x=edge(pos,pos-2);
			if(x==1)//如果与pos-2相连,看是否与pos-1相连
			{
				int y=edge(pos,pos-1);
				//如果与pos-1相连,说明一定为星
				if(y==1){
					cout<<"! 2"<<endl;
					cout<<endl;
					return ;
				}else{
					//不相连一定为链,因为这时候pos点已经连接了两个点了
					cout<<"! 1"<<endl;
					cout<<endl;
					return ;
				}
			}
			else{//当pos不于pos-2相连时,我们观察pos+1与pos-2和pos-1的关系
				//接下来就与上面相同了
				int y=edge(pos+1,pos-2);
				if(y==0){
					cout<<"! 1"<<endl;
					cout<<endl;
					return ;
				}else{
					int z=edge(pos+1,pos-1);
					if(z==1){
						cout<<"! 2"<<endl;
						cout<<endl;
						return ;
					}else{
						cout<<"! 1"<<endl;
						cout<<endl;
						return ;
					}
				}
			}
		}
		else{//开始特判当pos为1时
			int x=edge(1,3);
			if(x==1){
				int y=edge(1,4);
				if(y==1){
					cout<<"! 2"<<endl;
					cout<<endl;
					return ;
				}else{
					cout<<"! 1"<<endl;
					cout<<endl;
					return ;
				}
			}else{
				int y=edge(2,3);
				if(y==0){
					cout<<"! 1"<<endl;
					cout<<endl;
					return ;
				}else{
					int z=edge(2,4);
					if(z==1){
						cout<<"! 2"<<endl;
						cout<<endl;
						return ;
					}else{
						cout<<"! 1"<<endl;
						cout<<endl;
						return ;
					}
				}
			}
		}
}
int main(){
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

M题V-Diagram 

 

 

这道题一定要看清题,题中给的就是一个V图,就不用再排序了。然后针对于这个图,我们发现最大的有可能的三个范围实际上就是全部的sum/n或者是最低点左边的全部和加上右边第一个除以对应的个数或者是最低点右边的和加上最低点左边的数除以相应的个数,这个可以大概理解一下,因为如果说中间大,那么一定有两边的数大于中间的数,这时候就会提高平均值,所以最值一定会在端点处出现的,所以我们讨论这三种情况就行。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[300030];//注意用long long
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        ll mi=0x3f3f3f3f;
        int cnt=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]<mi){
                mi=a[i];
                cnt=i;
            }
        }
        ll sum=0;//直接开double不可以,因为输入时用int类型,转化为double会TLE
        ll sumL=0;
        ll sumR=0;
        for(int i=1;i<=cnt+1;i++){
            sumL+=a[i];
        }
        for(int i=cnt-1;i<=n;i++){
            sumR+=a[i];
        }
        for(int i=1;i<=n;i++){
            sum+=a[i];
        }
        cout<<fixed<<setprecision(10)<<max(max(1.0L*sumL/(cnt+1),1.0L*sumR/(n-cnt+2)),1.0L*sum/n)<<endl;
    }
    system("pause");
    return 0;
}

 这个代码中要注意的是,我们最后要保留9位输出的话,也就是意味着我们要使用double类型的变量,但输入时数据为int类型,这时候如果我们刚开始就把sum等变量设置为dounle类型,我们的每次输入计算机就要转化一次类型,从而导致TLE。因此我们直接用int接受,但最后使用出发求职的时候用1.0L*res这种方式使得结果变为double类型。

目前先讲解这三道题(主要目前就会这三道)吧,咳咳

2023 ICPC Asia Nanjing Regional Contest 也被称为 The 2nd Universal Cup. Stage 11 Nanjing,有多个目相关信息。 在目 F 中,第一行包含两个整数 \(n\) 和 \(m\)(\(1 \leq n, m \leq 10^5\)),分别表示操作的数量和序列的长度[^1]。 目 Knapsack 的输入第一行包含三个整数 \(n\)、\(W\) 和 \(k\)(\(1 \leq n \leq 5 \times 10^3\),\(1 \leq W \leq 10^4\),\(0 \leq k \leq n\)),分别表示商店中宝石的总数、拥有的钱数和可以免费拿取的宝石数量[^2]。 目 G.C 给出了对应的代码实现,代码中定义了常量 `mod = 998244353`,以及方向数组 `dx` 和 `dy`,使用了优先队列和动态规划来解决问。其功能是按照价格对物品排序,通过小根堆求出最大价值的前 \(k\) 大的物品,最后计算出最大价值并输出[^3]。 ```cpp #include<bits/stdc++.h> using namespace std; const int mod=998244353; int dx[4]={0,0,-1,1}; int dy[4]={-1,1,0,0}; #define int long long typedef pair<int,int> pii; const int N=10010; int dp[N]; pii a[N]; int suf[N]; void solve() { int n,m,k; cin>>n>>m>>k; for(int i=1;i<=n;i++)cin>>a[i].first>>a[i].second; sort(a+1,a+1+n); // 按照价格进行排序 priority_queue<int,vector<int>,greater<int>> q; // 小根堆,每次求最大价值的前k大的物品 int sum=0; for(int i=n;i>=1;i--) { sum+=a[i].second; q.push(a[i].second); if((int)q.size()>k) { sum-=q.top(); q.pop(); } suf[i]=sum; } int ans=0; for(int i=1;i<=n;i++) { for(int j=m;j>=a[i].first;j--) { dp[j]=max(dp[j],dp[j-a[i].first]+a[i].second); } ans=max(ans,dp[m]+suf[i+1]); } cout<<ans<<endl; } signed main() { int good_luck_to_you; ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); good_luck_to_you=1; //cin>>good_luck_to_you; while(good_luck_to_you--) { solve(); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值