暑假篇——NOIP2017模擬賽題解

目錄

一.優雅的序列

1.題目

2.題解 

3.Code

二.甲蟲入侵

1.題目

2.題解 

3.Code

三.大逃亡

1.題目

2.題解 

3.Code

 

謝謝!


雖然三道題上了200,但還是有點菜

一.優雅的序列

1.題目

點擊打開鏈接

2.題解 

這道題難就難在重複的數字上,如果沒有重複的數字,直接n-1。

不難發現,越小的數越要往前面放,但是又爲了儘量避免重複,我們就輪換着放,比如:

1 1 1 2 3 4 4 4 5

就應該變成:

1 2 3 4 5 1 4 1 4

這樣就能保證有最多對a[i] < a[i + 1];

具體實踐如下:

step1:把每個數字排序後的起點和重複數量存在一個pair數組內;

step2:用len表示最後排好的數組長度,每次枚舉每一個數字,直到枚舉完每一個數字爲止。

step3:統計滿足條件的i的個數。

3.Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
int n, k, len;
LL a[100005], ans, a1[100005];
pair <int, int> p[100005];
int main (){
	//freopen ("grace.in", "r", stdin);
	//freopen ("grace.out", "w", stdout);
	scanf ("%d", &n);
	for (register int i = 1; i <= n; i ++)
		scanf ("%lld", &a[i]);
	sort (a + 1, a + 1 + n);
	for (register int i = 2; i <= n; i ++){
		if (a[i] == a[i - 1]){
			int j;
			for (j = i; j <= n; j ++)
				if (a[j] != a[j - 1])
					break;
			p[++ k].first = i - 1;
			p[k].second = j - i + 1;
			i = j;
		}
		else{
			p[++ k].first = i - 1;
			p[k].second = 1;
		}
	}
	if (a[n] != a[n - 1]){
		p[++ k].first = n;
		p[k].second = 1;
	}
	while (len < n){
		for (register int i = 1; i <= k; i ++){
			if (p[i].second){
				a1[++ len] = a[p[i].first];
				p[i].first ++;
				p[i].second --;
			}
		}
	}
	for (register int i = 1; i <= len; i ++)
		if (a1[i] < a1[i + 1])
			ans ++;
	printf ("%lld\n", ans);
	return 0;
}

二.甲蟲入侵

1.題目

點擊打開鏈接

2.題解 

這道題是整個最難的題目,要用離散化+暴力搜索

首先輸入時可以把每次移動看做一個點,起點是(0,0)例如:樣例第一個就是:(8,0)

每次移動要存入兩個點,這是爲後面的離散化做準備的;

然後,對於我們存入的每一個點,我們要進行去重操作(裏面要排序),橫座標和縱座標分別進行。

接着就進行離散化,我存入的每一個點都對應他們自己的一個下標,就可以用這些下標表示他們的值,一共只有1000個點,離散化之後整個的空間就變成了2000。

然後再來標記農夫走過的田地,這裏我們用upper_bound找到農夫每次走之後的座標離散化之後的下標,把灑過農藥的田地標爲1。

接着暴力搜索一波,把甲蟲能到的位置標爲-1;

最後就是統計面積,我們先來看一看離散化之後農場的樣子:(標黃的是我們要求的不被甲蟲侵犯的面積)

相當於每一個點都被我擴散成了兩個點,那麼面積的求法就是1 * 4 + (x2 - x1 - 1) * (y1 - y2 + 1) + (y1 - y2 - 1) * (x2 - x1 + 1);

就這樣求面積就完了。

有點懵,上代碼:

3.Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define M 2005
int n, len[M], cntx, cnty, curx, cury, realx[M], realy[M], vis[M][M];
char dir[M];
int d[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
LL ans;
void unique (int *x, int &cnt){
	sort (x, x + cnt);
	int cnt1 = 1;
	for (int i = 1; i < cnt; i ++)
		if (x[i] != x[i - 1])
			x[cnt1 ++] = x[i];
	cnt = cnt1; 
}
bool pd (int tox, int toy){
	if (tox < 0 || tox >= cntx || toy < 0 || toy >= cnty || vis[tox][toy])
		return 0;
	return 1;
}
void DFS (int x, int y){
	vis[x][y] = -1;
	for (int i = 0; i < 4; i ++){
		int tox = x + d[i][0];
		int toy = y + d[i][1];
		if (pd (tox, toy))
			DFS (tox, toy);
	}
}
int main (){
	scanf ("%d", &n);
	for (int i = 1; i <= n; i ++){
		scanf ("\n%c %d", &dir[i], &len[i]);
		if (dir[i] == 'L'){
			realx[cntx ++] = curx + 1;
			realy[cnty ++] = cury;
			realx[cntx ++] = curx -= len[i];
			realy[cnty ++] = cury + 1;
		}
		if (dir[i] == 'R'){
			realx[cntx ++] = curx;
			realy[cnty ++] = cury;
			realx[cntx ++] = (curx += len[i]) + 1;
			realy[cnty ++] = cury + 1;
		}
		if (dir[i] == 'U'){
			realx[cntx ++] = curx;
			realy[cnty ++] = cury;
			realx[cntx ++] = curx + 1;
			realy[cnty ++] = (cury += len[i]) + 1;
		}
		if (dir[i] == 'D'){
			realx[cntx ++] = curx;
			realy[cnty ++] = cury + 1;
			realx[cntx ++] = curx + 1;
			realy[cnty ++] = cury -= len[i];
		}
	}
	unique (realx, cntx);
	unique (realy, cnty);
	int Indexx = lower_bound (realx, realx + cntx, curx = 0) - realx, 
		Indexy = lower_bound (realy, realy + cnty, cury = 0) - realy, 
		now;
	for (int i = 1; i <= n; i ++){
		if (dir[i] == 'L'){
			now = lower_bound (realx, realx + cntx, curx -= len[i]) - realx;
			for ( ; Indexx > now; Indexx --)
				vis[Indexx][Indexy] = 1;
		}
		if (dir[i] == 'R'){
			now = lower_bound (realx, realx + cntx, curx += len[i]) - realx;
			for ( ; Indexx < now; Indexx ++)
				vis[Indexx][Indexy] = 1;
		}
		if (dir[i] == 'U'){
			now = lower_bound (realy, realy + cnty, cury += len[i]) - realy;
			for ( ; Indexy < now; Indexy ++)
				vis[Indexx][Indexy] = 1;
		}
		if (dir[i] == 'D'){
			now = lower_bound (realy, realy + cnty, cury -= len[i]) - realy;
			for ( ; Indexy > now; Indexy --)
				vis[Indexx][Indexy] = 1;
		}
	}
	vis[Indexx][Indexy] = 1;
	for (int i = 0; i <= cntx; i ++){
		if (! vis[i][0]) DFS (i, 0);
		if (! vis[i][cnty]) DFS (i, cnty);
	}
	for (int i = 1; i < cnty; i ++){
		if (! vis[0][i]) DFS (0, i);
		if (! vis[cntx][i]) DFS (cntx, i);
	}
	for (int i = 1; i <= cntx; i ++){
		for (int j = 1; j <= cnty; j ++){
			if (~vis[i][j])
				ans += (LL) (realx[i] - realx[i - 1]) * (realy[j] - realy[j - 1]);
		}
	}
	printf ("%lld\n", ans);
	return 0;
}

三.大逃亡

1.題目

點擊打開鏈接

2.題解 

很簡單,因爲答案具有單調性,直接二分答案,然後暴力搜索檢查答案,注意有細節,特別是二分距離有可能是0

3.Code

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define M 10005
struct node {
	int xx, yy, step;
	node (){};
	node (int XX, int YY, int STEP){
		xx = XX;
		yy = YY;
		step = STEP;
	}
};
int n, X, Y, sx, sy, tx, ty, dx[M], dy[M], ans1, ans2, dis[1005][1005];
int dir[4][2] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
bool flag[1005][1005], vis[1005][1005];
int fabs (int x){
	if (x < 0)
		return -x;
	return x;
}
bool pd1 (int tox, int toy){
	if (tox < 0 || tox >= X || toy < 0 || toy >= Y || vis[tox][toy])
		return 0;
	return 1;
}
void prepare (){
	queue <node> Q;
	for (int i = 1; i <= n; i ++)
		Q.push (node (dx[i], dy[i], 0));
	while (! Q.empty ()){
		node f = Q.front ();
		if (! dis[f.xx][f.yy])
			dis[f.xx][f.yy] = f.step;
		Q.pop ();
		for (int i = 0; i < 4; i ++){
			int tox = f.xx + dir[i][0];
			int toy = f.yy + dir[i][1];
			if (pd1 (tox, toy)){
				vis[tox][toy] = 1;
				Q.push (node (tox, toy, f.step + 1));
			}
		}
	}
}
bool pd (int tox, int toy, int now){
	if (tox < 0 || tox >= X || toy < 0 || toy >= Y || vis[tox][toy] || dis[tox][toy] < now)
		return 0;
	return 1;
}
inline int BFS (int now){
	memset (vis, 0, sizeof vis);
	queue <node> Q;
	vis[sx][sy] = 1;
	Q.push (node (sx, sy, 0));
	while (! Q.empty ()){
		node f = Q.front ();
		Q.pop ();
		if (f.xx == tx && f.yy == ty)
			return f.step;
		for (register int i = 0; i < 4; i ++){
			int tox = f.xx + dir[i][0];
			int toy = f.yy + dir[i][1];
			if (pd (tox, toy, now)){
				vis[tox][toy] = 1;
				Q.push (node (tox, toy, f.step + 1));
			}
		}
	}
	return -1;
}
inline int check (int now){
	int tmp = BFS (now);
	return tmp;
}
int main (){
	//freopen ("escape.in", "r", stdin);
	//freopen ("escape.out", "w", stdout);
	int l = 0, r = 0x3f3f3f3f, mid;
	scanf ("%d %d %d %d %d %d %d", &n, &X, &Y, &sx, &sy, &tx, &ty);
	for (register int i = 1; i <= n; i ++){
		scanf ("%d %d", &dx[i], &dy[i]);
		r = min (r, fabs (dx[i] - sx) + fabs (dy[i] - sy));
		r = min (r, fabs (dx[i] - tx) + fabs (dy[i] - ty));
	}
	prepare ();
	int tmp;
	while (l + 1 < r){
		mid = (l + r) / 2;
		tmp = check (mid);
		if (tmp != -1){
			l = mid;
		}
		else
			r = mid - 1;
	}
	ans1 = l, ans2 = tmp;
	int tp = check (r);
	if (tp != -1)
		ans1 = r, ans2 = tmp;
	printf ("%d %d\n", ans1, ans2);
	return 0;
}

謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章