全国信息学奥林匹克联赛(NOIP2015)复赛模拟


1.足球联赛
(soccer.pas/c/cpp)
【问题描述】
巴蜀中学新一季的足球联赛开幕了。足球联赛有 n 只球队参赛,每赛季,每只球队要与
其他球队各赛两场,主客各一场,赢一场得 3 分,输一场不得分,平局两只队伍各得一分。
英勇无畏的小鸿是机房的主力前锋,她总能在关键时刻踢出一些匪夷所思的妙球。但是
很可惜,她过早的燃烧完了她的职业生涯,不过作为一个能够 Burning 的 girl,她的能力不
止如此,她还能预测这个赛季所有球队的比赛结果。
虽然她能准确预测所有比赛的结果,但是其实她不怎么厉害,Mr.Gao 上数学课时她总
是在 sleep,因此她的脑里只有整数没有实数,而且,她只会 10 以内非负整数的加法运算,
因此她只有结果却无法知道谁会获得联赛的冠军。
小鸿想给冠军队伍的所有队员一个拥抱,所以她把计算结果的任务交给了你:
现在,给你一个 n*n 的矩阵表示比赛情况。第 i 行第 j 列的字母表示在第 i 只队伍
在主场迎战第 j 只队伍的比赛情况,W 表示主队赢,L 表示主队输,D 表示平局。现在需
要你给出最后能得到小鸿拥抱的队伍编号,如有多支队伍分数最高,按字典序输出编号。
【输入格式】
第一行一个整数 n。
接下来 n 行,每行 n 个字符,表示输赢情况。
第 i 行第 i 列为 - ,因为一只队伍不可能与自己比赛。
【输出格式】
输出得分最高的队伍编号。如有多个在一行中输出,用一个空格分开。
【样例输入输出 1】
3
-WW
W-W
WW
【输出】
1 2 3
【样例输入输出 2】
5
-DWWD
L-WLL
DD-WD
DDL-L
DDLL
【输出】
1
数据范围】
对于 40%的数据,满足 N<=20
对于 100%的数据,满足 N<=50

zz模拟,毁我青春
#include<iostream>
#define inc(i,l,r) for(int i=l;i<=r;++i) 
using namespace std;
int ans[55],n;
char s[55];
int main()
{
	scanf("%d",&n);
	inc(i,1,n)
	{
		scanf("%s",s+1);
		inc(j,1,n)
		{
			if(s[j]=='L')ans[j]+=3;
			else if(s[j]=='W')ans[i]+=3;
			else if(s[j]=='D'){++ans[i];++ans[j];}
		}
	}
	
	int maxx=0;
	inc(i,1,n)
	maxx=max(maxx,ans[i]);
	inc(i,1,n)
	if(ans[i]==maxx)printf("%d ",i);
	return 0;
} 

2.最短路径
(paths.pas/c/cpp)
【问题描述】
平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在小 Y 想要知道在
每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强
迫症患者,他有许多奇奇怪怪的要求与限制条件:
1.从 A 走到 B 时,只能由横坐标小的点走到大的点。
2.由 B 回到 A 时,只能由横坐标大的点走到小的点。
3.有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。
请你帮他解决这个问题助他治疗吧!
【输入格式】
第一行三个整数 n,b1,b2,( 0 < b1,b2 < n-1 且 b1 <> b2)。n 表示点数,从 0 到 n-1 编
号,b1 和 b2 为两个特殊点的编号。
以下 n 行,每行两个整数 x、y 表示该点的坐标(0 <= x,y <= 2000),从 0 号点顺序
给出。Doctor Gao 为了方便他的治疗,已经将给出的点按 x 增序排好了。
【输出格式】
输出仅一行,即最短路径长度(精确到小数点后面 2 位)
【样例输入】
5 1 3
1 3
3 4
4 1
7 5
8 3
【输出】
18.18
【样例解释】
最短路径:0->1->4->3->2->0
【数据范围】
20%的数据 n<=20
60%的数据 n<=300
100%的数据 n<=1000
对于所有数据 x,y,b1,b2 如题目描述

题意:假设同时有X,Y两个人同时从A出发,向B走; 目标:X,Y不能走对方到达过的地方(A,B除外) 2. f[i][j]表示X走到i,Y走到j的最小值 3.由于每个点都要走,所以f[i][j]要么由f[i-1][j]转移,要么由f[i][j-1]转移 4.针对b1,可以看做只能由其中一个人走过(假设为A) 那么只存在f[b1][j],而f[i][b1]不予处理,b2同理
#include<bits/stdc++.h>
#define re return
#define D double 
#define inc(i,l,r) for(register int i=l;i<=r;++i) 
int maxn=200005;
using namespace std;
template<typename T>inline void rd(T&x)
{
	char c;bool f=0;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
	x=c^48;
	while((c=getchar())>='0'&c<='9')x=x*10+(c^48);
	if(f)x=-x;
}
double f[1005][1005],dis[1005][1005];
int n,o,p;
struct node{
	int x,y;
}pos[1005];
D cala(int x,int y)
{
	re x*x+y*y;
}
int main()
{
	//freopen("paths.in","r",stdin);
	//freopen("paths.out","w",stdout);
	rd(n);rd(o);rd(p);++o;++p;
	inc(i,1,n)rd(pos[i].x),rd(pos[i].y);
	
	inc(i,1,n)
	{
		f[i][i]=100000000;
		inc(j,i+1,n)
		{
		dis[i][j]=sqrt(cala(pos[i].x-pos[j].x,pos[i].y-pos[j].y));
		f[i][j]=f[j][i]=100000000;
		}
	}
	
	f[1][1]=0;
	inc(k,1,n)
	{
		if(p!=k&&o!=k)
		{
			inc(i,1,k-1)
			{
				f[k-1][k]=min(f[k-1][k],dis[i][k]+f[k-1][i]);
				f[i][k]=min(f[i][k],f[i][k-1]+dis[k-1][k]);
				f[k][k-1]=min(f[k][k-1],dis[i][k]+f[i][k-1]);
				f[k][i]=min(f[k][i],f[k-1][i]+dis[k-1][k]);
			}
		}
		else if(k==p)
		{
			inc(i,1,k-1)
			{
				f[k-1][k]=min(f[k-1][k],dis[i][k]+f[k-1][i]);
				f[i][k]=min(f[i][k],f[i][k-1]+dis[k-1][k]);
			}
		}
		else {
			inc(i,1,k-1)
			{
				f[k][k-1]=min(f[k][k-1],dis[i][k]+f[i][k-1]);
				f[k][i]=min(f[k][i],f[k-1][i]+dis[k-1][k]);
			}
		} 
	}
	D ans=105555555554; 
	inc(i,1,n-1)
	{
		ans=min(ans,f[i][n]+dis[i][n]);
		ans=min(ans,f[n][i]+dis[i][n]);
	}
	printf("%.2lf",ans);
	re 0;
}

3.阿 Q 的停车场
(park.pas/c/cpp)
【问题描述】
刚拿到驾照的 KJ 总喜欢开着车到处兜风,玩完了再把车停到阿 Q 的停车场里,虽然
她对自己停车的水平很有信心,但她还是不放心其他人的停车水平,尤其是 Kelukin。于是,
她每次都把自己的爱车停在距离其它车最远的一个车位。KJ 觉得自己这样的策略非常科
学,于是她开始想:在一个停车场中有一排车位,从左到右编号为 1 到 n,初始时全部是
空的。有若干汽车,进出停车场共 m 次。对于每辆进入停车场的汽车,会选择与其它车距
离最小值最大的一个车位,若有多个符合条件,选择最左边一个。KJ 想着想着就睡着了,
在她一旁的 Kelukin 想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把
这个问题就留给了你:在 KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输
出每辆车的车位编号。
【输入说明】
第一行,两个整数 n 和 m,表示停车场大小和操作数;
接下来 m 行,每行两个整数 F 和 x
F 是 1 表示编号为 x 的车进停车场;
F 是 2 表示编号为 x 的车出停车场;
保证操作合法,即:
出停车场的车一定目前仍在停车场里;
停车场内的车不会超过 n;
【输出说明】
于所有操作 1,输出一个整数,表示该车车位的编号。
【样例输入】
7 11
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8
输出
1
7
4
2
7
4
1
3
【数据范围】
对 30%的数据 n<=1000 ,m<=1000
对 60%的数据 n<=200000,m<=2000
对 100%的数据 n,m<=200000,车的编号小于等于 10^6

线段树(维护四个标记)

详见大佬思路
不过貌似代码用一点点小错误,
特此献上我的诡奇代码

#include<bits/stdc++.h>
#define re return
#define lson rt<<1
#define rson rt<<1|1
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=200003;
using namespace std;
template<typename T>inline void rd(T&x)
{
	char c;bool f=0;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
	x=c^48;
	while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
	if(f)x=-x;
}

int n,m,opt,hide[10000005];
struct node{
	int x,y,mid,p;
}t[maxn<<2];

inline void update(int rt)
{
	t[rt].x=t[lson].x;
	if(!t[rt].x)t[rt].x=t[rson].x;
	
	t[rt].y=t[rson].y;
	if(!t[rt].y)t[rt].y=t[lson].y;
	
	t[rt].mid=t[lson].mid;t[rt].p=t[lson].p;
	if(t[rt].mid<t[rson].mid){
		t[rt].mid=t[rson].mid;t[rt].p=t[rson].p;
	}
	if(t[rson].x&&t[lson].y&&((t[rson].x-t[lson].y)/2>t[rt].mid)||((t[rson].x-t[lson].y)/2==t[rt].mid&&((t[lson].y+t[rson].x)/2<t[rt].p)))
	{
	//小细节2:判断相等情况,优先选左
		t[rt].mid=(t[rson].x-t[lson].y)/2;
		t[rt].p=(t[lson].y+t[rson].x)/2;
	}
}
void add(int rt,int l,int r,int pos,int f)
{
	if(l==r)
	{
		if(f)
		{
			t[rt].x=t[rt].y=l;
			t[rt].mid=t[rt].p=0;
		} 
		else 
		{
			t[rt].x=t[rt].y=0;
			t[rt].mid=1;t[rt].p=l;
		}
		re ;
	}
	int mid=(l+r)>>1;
	if(mid<pos)add(rson,mid+1,r,pos,f);
	else add(lson,l,mid,pos,f);
	update(rt); 
}
int tot,visx,visn;
int main()
{
	int x;
	rd(n),rd(m);
	inc(i,1,m)
	{
		rd(opt),rd(x);
		if(opt==1)
		{	
			if(!t[1].x||(!visx&&(t[1].x-1>=t[1].mid))){hide[x]=1;visx=1;}
			else if(!visn&&n-t[1].y>t[1].mid){hide[x]=n;visn=1;}
			//小细节1:判断1,n位置是否该放,做好标记
			else hide[x]=t[1].p;
			add(1,1,n,hide[x],1);
			printf("%d\n",hide[x]);
		}
		else {
			add(1,1,n,hide[x],0);
			if(hide[x]==1)visx=0;
			else if(hide[x]==n)visn=0;
		}
	}
	re 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值