习题8-16(uva-1618)

#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>


#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
using namespace std;
class STTable
{
    
    
	const int STMAXSIZE = 20;
public:
	
	STTable() {
    
    }
	~STTable() {
    
    
		lg2.clear();
		dpmin.clear();
		dpmax.clear();
	};
	void Init(int* input, int cnt)
	{
    
    
		lg2.assign(cnt + 1, -1);
		dpmin.assign(cnt, vector<int>(STMAXSIZE, 0));
		dpmax.assign(cnt, vector<int>(STMAXSIZE, 0));

		for (int i = 1; i <= cnt; i++)
			lg2[i] = lg2[i - 1] + (i & (i - 1) ? 0 : 1);

		for (int i = 0; i < cnt; i++) {
    
    
			dpmin[i][0] = dpmax[i][0] = input[i];
		}

		int len = lg2[cnt];
		for (int i = 1; i <= len; i++) {
    
    
			for (int j = 0; lg2[cnt - j] >= i; j++)
			{
    
    
				dpmin[j][i] = min(dpmin[j][i - 1], dpmin[j + (1 << (i - 1))][i - 1]);
				dpmax[j][i] = max(dpmax[j][i - 1], dpmax[j + (1 << (i - 1))][i - 1]);
			}
		}
	}
	int GetMin(int l, int r) {
    
    
		int k = lg2[r - l + 1];    //找到当前区间最大的倍增长度
		return min(dpmin[l][k], dpmin[r - (1 << k) + 1][k]);
	}
	int GetMax(int l, int r) {
    
    
		int k = lg2[r - l + 1];    //找到当前区间最大的倍增长度
		return max(dpmax[l][k], dpmax[r - (1 << k) + 1][k]);
	}
private:
	vector<int> lg2;
	vector<vector<int> > dpmin,dpmax;
};

const int maxn = 1e4 + 7,maxm = 100010;
int n,input[maxn],pos[maxm];

int main()
{
    
    
	int t;
	STTable st;
	cin >> t;
	while (t--) {
    
    
		cin >> n;
		for (int i = 0; i < n; i++) {
    
    
			cin >> input[i];
			//每个输入都不同 所有每个下标不会出现覆盖的情况
			pos[input[i]] = i;
		}
		st.Init(input, n);
		bool ok = false;
		for (int i = 0; i < n; i++) {
    
    
			for (int j = i + 3; j < n; j++) {
    
    
				int tmin = st.GetMin(i, j);
				int tmax = st.GetMax(i, j);
				// p q r s   p == i   s == j
				// q > s > p > r
				//排列 q  >  input[j] > input[i] > r
				//tmax > input[j] > input[i] > tmin 
				//i pos[tmax] pos[tmin ] j
				//极端情况 tmin = input[i] pos[tmax] 无法排在pos[tmin]前面
 				if (input[j] > input[i]  && pos[tmax] < pos[tmin]) {
    
    
					ok = true;
					break;
				}
				// q < s < p < r
				//排列 q  <  input[j] < input[i] < r
				//tmin < input[j] < input[i] < tmax
				// q ==> tmin  r ==>tmax  
				//i pos[tmin] pos[tmax] j
				//因为input[j] < input[i]  tmax 不会是 input[j]
				//tmin 不会是 input[i]
				if (input[j] < input[i] &&  pos[tmin] < pos[tmax] ) {
    
    
					ok = true;
					break;
				}
			}
			if (ok) break;
		}
		if (ok) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/seanbill/article/details/117380382