The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou)

Dashboard - The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou) - Codeforces

to sum of:从结果上来看,是打的最好的一次(铜首),罚时少75左右到银牌区了。过程也顺利,陆陆续续都在有题出,最后一个小时过了还出了两题。签到题智慧了一下35分钟出的,虽然wa了一发,但是也没有卡太久,如果没有智慧一下的话,不知道还会卡多久..然后出的第二题是交互题,第三题是从开场到后场队友一直在想的构造题,我没有看,想不来..然后第四题是期望题,也是队友写的,我完全写不来一点。然后最一题是一个最短路,思路出的挺快,但是不确定,后来还换了别的想法,都实现不了。然后倒回去想一开始那个,发现的确完全是可以那样写的。敲了一发没测样例wa1,然后再交TLE4,再把unordered_map换成数组(一开始以为太大了)跑了1700ms,给了2s,可以跑过。题解说还能把优先队列给优化了,但是不是很清楚。总的来说,在成都赛站前能打这么一次顺利的,优异的vp,可以了,士气大涨!

按出题顺序:

Problem - M - Codeforces--V-Diagram

思路:签到题,还是得智慧一下,不然卡多久都不知道。智慧:如果决定把最大的值去掉,那一边就应该全部都去掉。另一边也是。所以只有几种情况匹配,要么两边都不删,要么都删,要么删其中一边。取max即可。

void solve(){
	cin >> n;
	double sum=0;
	double sum1=0,sum2=0,sum3=0;
	int idx=0;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		if(i>1 && a[i-1]<a[i] && a[i-1]<a[i-2]) idx=i-1;
		sum+=a[i];
	}
	for(int i=1;i<=idx+1;i++) sum1+=a[i];
	for(int i=idx-1;i<=n;i++) sum2+=a[i];
	sum3=a[idx-1]+a[idx]+a[idx+1];
	double ns=sum;
	double avg=sum/n;
	avg=max({sum1/(idx+1),sum2/(n-idx+2),sum3/3,avg,ns/n});
	cout << fixed << setprecision(11) << avg << "\n";
}

Problem - J - Codeforces--MysteriousTree

思路:交互题。只能问500+3次,容易发现,只要在500次之内问出来一条边,那么剩下三次肯定可以得出结论。一开始想着固定一个数字,然后一直问奇数,发现是不行的。后来发现只要1,2--3,4--5,6--7,8--这样问,500次肯定可以问出一条边,如果一直没有边那肯定就是链,否则需要再用三次判断一下。

int n;
void solve(){
	cin>>n;
	int u=1,v=2;
	if(n%2==0){
		int ans=0;
		while(1){
			cout<<"? "<<u<<" "<<v<<endl;	
			cin>>ans;
			if(ans==1){
				if(u-1>=1) cout<<"? "<<u<<" "<<u-1<<endl;	
				else cout<<"? "<<u<<" "<<v+1<<endl;	
				cin>>ans;
				if(ans==1){ 
					if(u-1>=1&&u-2>=1) cout<<"? "<<u<<" "<<u-2<<endl;	
					else if(u-1>=1&&u-2<1) cout<<"? "<<u<<" "<<v+1<<endl;
					else cout<<"? "<<u<<" "<<v+1+1<<endl;
					cin>>ans;
					if(ans==1){ cout<<"! 2"<<endl; return; }
					else { cout<<"! 1"<<endl; return; }
				}
				else{
					if(u-1>=1) cout<<"? "<<v<<" "<<u-1<<endl;	
					else cout<<"? "<<v<<" "<<v+1<<endl;	
					cin>>ans;
					if(ans==1){
						if(u-1>=1&&u-2>=1) cout<<"? "<<v<<" "<<u-2<<endl;	
						else if(u-1>=1&&u-2<1) cout<<"? "<<v<<" "<<v+1<<endl;
						else cout<<"? "<<v<<" "<<v+1+1<<endl;
						cin>>ans;
						if(ans==1){ cout<<"! 2"<<endl; return; }
						else { cout<<"! 1"<<endl; return; }
					}
					else{ cout<<"! 1"<<endl; return; }
				}
			}
			else {
				if(u==n-1&&v==n){ cout<<"! 1"<<endl; return; }
				u+=2,v+=2;
			}
		}
	}
	else{
		int ans=0;
		while(1){
			cout<<"? "<<u<<" "<<v<<endl;	
			cin>>ans;
			if(ans==1){
				if(u-1>=1) cout<<"? "<<u<<" "<<u-1<<endl;	
				else cout<<"? "<<u<<" "<<v+1<<endl;	
				cin>>ans;
				if(ans==1){ 
					if(u-1>=1&&u-2>=1) cout<<"? "<<u<<" "<<u-2<<endl;	
					else if(u-1>=1&&u-2<1) cout<<"? "<<u<<" "<<v+1<<endl;
					else cout<<"? "<<u<<" "<<v+1+1<<endl;
					cin>>ans;
					if(ans==1){ cout<<"! 2"<<endl; return; }
					else { cout<<"! 1"<<endl; return; }
				}
				else{
					if(u-1>=1) cout<<"? "<<v<<" "<<u-1<<endl;	
					else cout<<"? "<<v<<" "<<v+1<<endl;	
					cin>>ans;
					if(ans==1){
						if(u-1>=1&&u-2>=1) cout<<"? "<<v<<" "<<u-2<<endl;	
						else if(u-1>=1&&u-2<1) cout<<"? "<<v<<" "<<v+1<<endl;
						else cout<<"? "<<v<<" "<<v+1+1<<endl;
						cin>>ans;
						if(ans==1){ cout<<"! 2"<<endl; return; }
						else { cout<<"! 1"<<endl; return; }
					}
					else{ cout<<"! 1"<<endl; return; }
				}
			}
			else if(u==n-2) u++,v++;
			else {
				if(u==n-1&&v==n){ cout<<"! 1"<<endl; return; }
				u+=2,v+=2;
			}
		}
	}
}

D (codeforces.com)--OperatorPrecedence  

思路:队友写的构造题,不懂。

bool check(vector<int> ans) {
	int r1 = 0, r2 = 0;
	for (int i = 1;i < (int)ans.size(); i += 2) {
		r1 += (ans[i] * ans[i + 1]);
	}
	r2 = ans[1] * ans.back();
	for (int i = 2; i < (int)ans.size() - 1; i += 2) {
		r2 *= (ans[i] + ans[i + 1]);
	}
	return (r1 == r2) && r1;
}
 
void solve(){
	cin >> n;
	if (n == 2) {
		cout << "1 -3 -3 1" << '\n';
		return ;
	}
	vector<int> ans(n * 2 + 1);
	if (n & 1) {
		vector<int> t = {-2, 2, 2, -2}, tt = {1, 1, -1, -1};
		for (int i = 2, j = 0; i <= n * 2; i += 2, j ++) {
			j %= 4;
			ans[i] = t[j];
		}
		for (int i = 1, j = 0; i <= n * 2; i += 2, j ++) {
			j %= 4;
			ans[i] = tt[j];
		}
	} else {
		vector<int> t = {-2, 2, 2, -2}, tt = {1, 1, -1, -1};
		for (int i = 2, j = 0; i <= n * 2; i += 2, j ++) {
			j %= 4;
			ans[i] = t[j];
		}
		for (int i = 1, j = 0; i <= n * 2; i += 2, j ++) {
			j %= 4;
			ans[i] = tt[j];
		}
		if (n % 4 == 2) {
			ans[n * 2] = 1;
			ans[n * 2 - 2] = 1;
		} else {
			ans[n * 2] = 2;
			ans[n * 2 - 2] = 4;
		}
	}
	for (int i = 1; i <= n * 2; i ++) cout << ans[i] << ' ';
	cout << '\n';
//	if (check(ans)) cout << "YES" << '\n';
//	else cout << "NO"<< '\n';
}

Problem - H - Codeforces--SugarSweet2

思路:队友写的期望题,不懂。

ll n;
ll qpow(ll a,ll n){
	ll res=1;
	while(n){
		if(n&1) (res*=a)%=mod;
		(a*=a)%=mod;
		n>>=1;
	}
	return res;
}
ll fac[N],inv[N];
void init(int x){
	fac[0]=1;
	for(int i=1;i<=x;i++) fac[i]=fac[i-1]*i%mod;
	inv[x]=qpow(fac[x],mod-2);
	for(int i=x-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll a[N],b[N],w[N];
ll c[N];
int fa[N];
int fnd(int x){
	return fa[x]==x?x:fa[x]=fnd(fa[x]);
}
bool vi[N];
int dfs(int x){
	vi[x]=1;
	if(b[x]==x){c[x]=a[x]; return 0;}
	if(a[b[x]]+w[b[x]]<=a[x]){
		c[x]=a[x];
		return 0;
	}
	if(a[b[x]]>a[x]){
		c[x]=(a[x]+w[x])%mod;
		return 1;
	}
	int to=b[x];
	if(fnd(to)==x){c[x]=a[x]; return 0;}
	fa[x]=to;
	ll res=dfs(to);
	if(!res){c[x]=a[x]; return 0;}
	else c[x]=(a[x]+w[x]*inv[res+1]%mod)%mod;
	return res+1;
}
void solve(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		fa[i]=i,vi[i]=0;
	}
	for(int i=1;i<=n;i++){
		cin >> b[i];
	}
	for(int i=1;i<=n;i++){
		cin >> w[i];
	}
	for(int i=1;i<=n;i++) if(!vi[i]) dfs(i);
	for(int i=1;i<=n;i++) cout << c[i] << " \n"[i==n];
}

Problem - G - Codeforces--SnakeMove

思路:非常容易发现是最短路,但是怎么处理与身体碰撞?其实只需要考虑一开始的静态的位置,后面动起来之后蛇身变化的位置没必要维护,因为我头到达的地方肯定是合法的位置,而只有我的蛇头到达过了那个点,蛇身才会在后来到达那个点。除了一开始蛇身会发生碰撞,后面bfs中可能会发生的碰撞是完全不用考虑的,因为肯定是更劣的,第一次蛇头到达才是更优的。那么只跑最短路,然后期间判断一下一开始是蛇身即可。因为用了优先队列,时间复杂度是o(nm*log(nm))的,给了2s,跑了1700ms。题解说可以优化成用普通队列o(nm)就行,暂时不是清楚..

int n,m,k;
int have[10000010];
char maze[3003][3003];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
unsigned long long dis[3003][3003];
bool vis[3003][3003];
inline void dijkstra(int x0,int y0){
	dis[x0][y0]=0;
	priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<>> pq;
	pq.push({0,{x0,y0}});
	while(pq.size()){
		pair<int,int> from=pq.top().second;
		pq.pop();
		int xx0=from.first,yy0=from.second;
		if(vis[xx0][yy0]) continue;
		vis[xx0][yy0]=1;
		for(int i=0;i<4;i++){
			int x=xx0+dx[i];
			int y=yy0+dy[i];
			if(x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&maze[x][y]!='#'){
				if(have[(x-1)*m+y]==k-2&&xx0==x0&&yy0==y0){
					dis[x][y]=k-1;
					pq.push({dis[x][y],{x,y}});
				}
				else if(have[(x-1)*m+y]!=0&&dis[xx0][yy0]+1>(unsigned long long)have[(x-1)*m+y]){
					if(dis[x][y]>dis[xx0][yy0]+1){
						dis[x][y]=dis[xx0][yy0]+1;
						pq.push({dis[x][y],{x,y}});
					}
				}	
				else if(have[(x-1)*m+y]!=0){
					if(dis[x][y]>have[(x-1)*m+y]-(dis[xx0][yy0]+1)+1+dis[xx0][yy0]+1){
						dis[x][y]=have[(x-1)*m+y]-(dis[xx0][yy0]+1)+1+dis[xx0][yy0]+1;
						pq.push({dis[x][y],{x,y}});
					}
				}
				else{
					if(dis[x][y]>dis[xx0][yy0]+1){
						dis[x][y]=dis[xx0][yy0]+1;
						pq.push({dis[x][y],{x,y}});
					}
				}
			}
		}
	}
}
void solve(){
	cin>>n>>m>>k;
	int x0,y0;
	for(int i=1;i<=k;i++){
		int x,y; cin>>x>>y;
		have[(x-1)*m+y]=k-i;
		if(i==1) x0=x,y0=y;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>maze[i][j];
			dis[i][j]=INT_MAX/2;
		}
	}
	dijkstra(x0,y0);
	unsigned long long ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(dis[i][j]!=INT_MAX/2) ans+=dis[i][j]*dis[i][j];
//			cout<<dis[i][j]<<" ";
		}
//		cout<<"\n";
	}
	cout<<ans;
}

//勿以小赢而不麻

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值