CCF軟體能力認證-第一次-視窗

DawnTraveler發表於2024-05-23

1.題目

問題描述

在某圖形作業系統中,有 N 個視窗,每個視窗都是一個兩邊與座標軸分別平行的矩形區域。視窗的邊界上的點也屬於該視窗。視窗之間有層次的區別,在多於一個視窗重疊的區域裡,只會顯示位於頂層的視窗裡的內容。
當你點選螢幕上一個點的時候,你就選擇了處於被點選位置的最頂層視窗,並且這個視窗就會被移到所有視窗的最頂層,而剩餘的視窗的層次順序不變。如果你點選的位置不屬於任何視窗,則系統會忽略你這次點選。
現在我們希望你寫一個程式模擬點選視窗的過程。

輸入格式

輸入的第一行有兩個正整數,即 N 和 M。(1 ≤ N ≤ 10,1 ≤ M ≤ 10)
接下來 N 行按照從最下層到最頂層的順序給出 N 個視窗的位置。 每行包含四個非負整數 x1, y1, x2, y2,表示該視窗的一對頂點座標分別為 (x1, y1) 和 (x2, y2)。保證 x1<x2 , y1<y2。
接下來 M 行每行包含兩個非負整數 x, y,表示一次滑鼠點選的座標。
題目中涉及到的所有點和矩形的頂點的 x, y 座標分別不超過 2559 和 1439。

輸出格式

輸出包括 M 行,每一行表示一次滑鼠點選的結果。如果該次滑鼠點選選擇了一個視窗,則輸出這個視窗的編號(視窗按照輸入中的順序從 1 編號到 N);如果沒有,則輸出"IGNORED"(不含雙引號)。

樣例輸入

3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5

樣例輸出

2
1
1
IGNORED

樣例說明

第一次點選的位置同時屬於第 1 和第 2 個視窗,但是由於第 2 個視窗在上面,它被選擇並且被置於頂層。

第二次點選的位置只屬於第 1 個視窗,因此該次點選選擇了此視窗並將其置於頂層。現在的三個視窗的層次關係與初始狀態恰好相反了。

第三次點選的位置同時屬於三個視窗的範圍,但是由於現在第 1 個視窗處於頂層,它被選擇。

最後點選的 (0, 5) 不屬於任何視窗。

2.題解

2.1 陣列順序->層級關係

思路

這題我們很容易知道,只要操作點選的座標位於某個視窗限制的座標之內,那麼我們就可以判定是選中了這個視窗;
難點是在視窗之間存在重疊關係,我們如何知道選中的是那個視窗? 選中之後該視窗層級提升到最高層,又如何更新該層級關係?

這裡我們巧妙利用陣列順序儲存了視窗之間的層級關係
據題意,剛開始時的輸入順序就是視窗的初始層級關係,越往後輸入的層級越高.
所以在第一次操作點選的時候,我們選擇點選最外層的視窗,也就是我們可以選擇從外向內遍歷(對於陣列順序來說,就是倒序遍歷),如果存在符合項,即輸出其編號
同時,我們將該陣列元素轉移到最外層層級(也就是陣列pos[n-1]),具體做法就是使用erase將這個元素從陣列中刪除,然後再新增到末尾即可

由於這裡我們移動了元素,必然需要單獨儲存原來的編號值,所以除了座標外,我們還需要單獨儲存每個視窗的編號值

程式碼

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n, m;
	cin >> n >> m;
	vector<vector<int>> pos(n, vector<int>(5));
	
	// 初始化位置陣列
	for(int i = 0; i < n; i++){
		for(int j = 0; j < 4; j++){
			cin >> pos[i][j];
		}
		pos[i][4] = i + 1; // 記錄編號
	}
	
	// 進行點選操作
	for(int i = 0; i < m; i++){
		int x, y, idx;
		cin >> x >> y;
		for(idx = n - 1; idx >= 0; idx--){
			int x1 = pos[idx][0], y1 = pos[idx][1], x2 = pos[idx][2], y2 = pos[idx][3];
			if((x <= x2 && x >= x1) && (y <= y2 && y >= y1)){
				cout << pos[idx][4] << endl;
				vector<int> temp = pos[idx];
				pos.erase(pos.begin() + idx); // 刪除第 idx 個元素(這裡不要想著需要-1,因為begin是從0開始的,所以當前下標對應的總個數本來就要+1,和這個-1抵消掉了)
				pos.push_back(temp); // 將儲存的元素新增到末尾
				break;
			}
		}
		if(idx < 0) cout << "IGNORED" << endl;
	}
	
	return 0;
}

相關文章