[囍报] CSP提高组模拟1

CSP提高组模拟1

\(我曾经说过:\)

\[\LARGE \color{red}不唐我都不带写的 \]

\(这回不是比赛唐了\)

\[\LARGE 是我唐 \]

没想到沉浸在更换评测姬喜悦之中的我这么快就迎来了当头一棒:

\[\LARGE 她十分甚至九分的 \color{red} {不支持} \color{black}ifdef ONLINE\_JUDGE \]

导致我全部 \(RE\)

\[\LARGE \color{red} 囍爆零 \]

题解鸽会...

T1 最短路

一眼Floyd,但没想到还需要迭代。

赛时开了两个二维数组一个记最短路一个记\(i\)\(j\)的最大点权,在Floyd上稍微改改就可以了。

赛时代码,再跑两遍Floyd就能AC

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rd read()
#define mkp make_pair
int read(){
	int f=1,x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return f*x;
}
const int N=400;

int n,m,q,ans[N][N],mp[N][N],pt[N];

void floyd(){
	for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++){
        	for(int j=1;j<=n;j++){
        		if(mp[i][j]+ans[i][j]>mp[i][k]+mp[k][j]+max(ans[i][k],ans[k][j])){
					mp[i][j]=mp[i][k]+mp[k][j];
					ans[i][j]=max(ans[i][k],ans[k][j]);
				}
			}   
		}        	
}

signed main(){
	#ifdef ONLINE_JUDGE//就是这玩意害我一分没有
	freopen("path.in","r",stdin);
	freopen("path.out","w",stdout);
	#endif
	
	memset(mp,0x3f,sizeof(mp));
	
	n=rd,m=rd,q=rd;
	for(int i=1;i<=n;i++){
		pt[i]=rd;
	}
	for(int i=1;i<=m;i++){
		int x=rd,y=rd,w=rd;
		mp[x][y]=mp[y][x]=min(mp[x][y],w);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			ans[i][j]=max(pt[i],pt[j]);
		}
		mp[i][i]=0;
	}
	floyd();
	for(int i=1;i<=q;i++){
		int x=rd,y=rd;
		printf("%lld\n",(mp[x][y]+ans[x][y])>=0x3f3f3f3f3f3f3f?-1:(mp[x][y]+ans[x][y]));
	}
	return 0;
}

赛后经点拨知道可以通过排序,按点权从小到大枚举中转点,保证当前求出的最短路能够经过的点只有点权不大于某值的点来更新ans。

赛后排序做法

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rd read()
#define mkp make_pair
int read(){
	int f=1,x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return f*x;
}
const int N=400;

int n,m,q,ans[N][N],mp[N][N];

struct node{
	int val,id;
}e[N];

bool cmp(node x, node y){
	if(x.val==y.val) return x.id<y.id;
	return x.val<y.val;
}

void floyd(){
	for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++){
        	if(e[i].id!=e[k].id){
	        	for(int j=1;j<=n;j++){
	        		if(e[i].id!=e[j].id && e[k].id!=e[j].id){
	        			mp[e[i].id][e[j].id]=min(mp[e[i].id][e[j].id],mp[e[i].id][e[k].id]+mp[e[k].id][e[j].id]);
	        			ans[e[i].id][e[j].id]=min(ans[e[i].id][e[j].id],mp[e[i].id][e[j].id]+max({e[i].val,e[j].val,e[k].val}));
					}
				}   
			}
		}        	
}

signed main(){
	freopen("path.in","r",stdin);
	freopen("path.out","w",stdout);
	
	memset(mp,0x3f,sizeof(mp));
	memset(ans,0x3f,sizeof(ans));
	
	n=rd,m=rd,q=rd;
	for(int i=1;i<=n;i++){
		e[i].val=rd;
		e[i].id=i;
	}
	
	sort(e+1,e+1+n,cmp);
	
	for(int i=1;i<=m;i++){
		int x=rd,y=rd,w=rd;
		mp[x][y]=mp[y][x]=min(mp[x][y],w);
	}
	floyd();
	for(int i=1;i<=q;i++){
		int x=rd,y=rd;
		printf("%lld\n",ans[x][y]!=0x3f3f3f3f3f3f3f3f?ans[x][y]:-1);
	}
	return 0;
}

T2 方格取数

赛时思路对了 也许吧

显然,某个点权值如果 \(k > 2*k\) 则不选;如果正好在区间内就直接出答案

显然,一个权值和\(>2∗k\)的矩形一定可以找到一个子矩形权值和\(\geq k\)\(\leq 2∗k\)

考虑一行一行删,有一行\(>2∗k\)就一格一格删,找到权值和最大的子矩形就彳亍了

这个码比赛时的也没改动啥
只不过是把ifdef ONLINE_JUDGE删了,横纵坐标反一下,int x,xx,y,yy放到全局变量(不理解为啥必须放到全局变量,DEV压根就没报错)就AC了

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rd read()
int read(){
	int f=1,x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return f*x;
}
const int N=2e3+100;

int n,k,h[N][N],lt[N][N],rt[N][N],a[N][N],sum[N][N];
int x,y,xx,yy;
int work(int x1,int y1,int x2,int y2){
	return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
}

signed main(){
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	
	n=rd,k=rd;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			a[i][j]=rd;
			if(a[i][j]>=k&&a[i][j]<=2*k){
				printf("%lld %lld %lld %lld",i,j,i,j);
				return 0;
			}
			if(a[i][j]>k*2) continue;
			h[i][j]=1;
			lt[i][j]=rt[i][j]=j; 
		}
	}
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
		}
	}
	
	for(int i=1;i<=n;i++){
		for(int j=2;j<=n;j++){
			if(a[i][j]<k&&a[i][j-1]<k){
				lt[i][j]=min(lt[i][j],lt[i][j-1]);
			}
		}
	}
	
	for(int i=1;i<=n;i++){
		for(int j=n-1;j>=1;j--){
			if(a[i][j]<k&&a[i][j+1]<k){
				rt[i][j]=max(rt[i][j],rt[i][j+1]);
			}
		}
	}
	
	for(int i=2;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(a[i][j]<k&&a[i-1][j]<k){
				h[i][j]=h[i-1][j]+1;
				lt[i][j]=max(lt[i][j],lt[i-1][j]);
				rt[i][j]=min(rt[i][j],rt[i-1][j]);
			}
		}
	}
	
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(work(i-h[i][j]+1,lt[i][j],i,rt[i][j])>=k){
				x=i-h[i][j]+1;
				y=lt[i][j];
				xx=i;
				yy=rt[i][j];
				break;
			}
		}
	}
	
	if(!x){
		printf("-1\n");
		return 0;
	}
	
	while(work(x,y,xx,yy)>2*k){
		if(x<xx){
			if(work(x,y,xx-1,yy)<k){
				x=xx;
			}else{
				xx--;
			}
		}else{
			yy--;
		} 
	}
	printf("%lld %lld %lld %lld\n",x,y,xx,yy);
	return 0;
}

T3 数组

鸽了

T4 树

T3都鸽了你还想着T4呢?

posted @ 2024-07-12 19:09  Elaina_0  阅读(16)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end