首页 > 其他分享 >CodeForces 1887D Split

CodeForces 1887D Split

时间:2023-10-28 13:55:07浏览次数:39  
标签:typedef int top CodeForces long maxn 1887D define Split

洛谷传送门

CF 传送门

\(a_l, a_{l + 1}, \ldots a_r\) 是好的当且仅当 \(\exists k \in [l, r - 1], \max\limits_{i = l}^k a_i < \min\limits_{i = k + 1}^r a_i\),称此时的 \(k\) 为分割点。

对 \(r\) 扫描线,单调栈维护极长的一些区间 \([L_i, R_i]\) 使得 \(\min\limits_{j = L_i}^r a_j = \min\limits_{j = R_i}^r a_j\)。由 \(\max\) 的不减性可得以 \(L_i\) 为分割点一定不劣。

可以 ST 表 + 二分对每个 \(L_i\) 求出一个 \(b_i\) 使得 \(l\) 取 \([b_i, L_i - 1]\) 时,\([l, r]\) 以 \(L_i\) 为分割点是好的。

把 \([b_i, L_i - 1]\) 扔到树状数组上,如果对于一个询问的 \(l\) 有区间覆盖它就合法。

时间复杂度 \(O((n + q) \log n)\)。

code
// Problem: D. Split
// Contest: Codeforces - Codeforces Round 905 (Div. 1)
// URL: https://codeforces.com/contest/1887/problem/D
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;

const int maxn = 300100;
const int logn = 20;

int n, a[maxn], m, stk[maxn], top, f[maxn][logn], ans[maxn];
pii b[maxn];
vector<pii> vc[maxn];

namespace BIT {
	int c[maxn];
	
	inline void update(int x, int d) {
		for (int i = x; i <= n; i += (i & (-i))) {
			c[i] += d;
		}
	}
	
	inline void update(int l, int r, int x) {
		update(l, x);
		update(r + 1, -x);
	}
	
	inline int query(int x) {
		int res = 0;
		for (int i = x; i; i -= (i & (-i))) {
			res += c[i];
		}
		return res;
	}
}

inline int qmax(int l, int r) {
	int k = __lg(r - l + 1);
	return max(f[l][k], f[r - (1 << k) + 1][k]);
}

void solve() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		f[i][0] = a[i];
	}
	scanf("%d", &m);
	for (int i = 1, l, r; i <= m; ++i) {
		scanf("%d%d", &l, &r);
		vc[r].pb(l, i);
	}
	for (int j = 1; (1 << j) <= n; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
			f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
		}
	}
	for (int i = 1; i <= n; ++i) {
		while (top && a[stk[top]] > a[i]) {
			BIT::update(b[top].fst, b[top].scd, -1);
			--top;
		}
		int j = stk[top] + 1;
		stk[++top] = i;
		int l = 1, r = j - 1, pos = j;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (qmax(mid, j - 1) < a[i]) {
				pos = mid;
				r = mid - 1;
			} else {
				l = mid + 1;
			}
		}
		b[top] = mkp(pos, j - 1);
		BIT::update(pos, j - 1, 1);
		for (pii p : vc[i]) {
			int l = p.fst, id = p.scd;
			ans[id] = (BIT::query(l) ? 1 : 0);
		}
	}
	for (int i = 1; i <= m; ++i) {
		puts(ans[i] ? "Yes" : "No");
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:typedef,int,top,CodeForces,long,maxn,1887D,define,Split
From: https://www.cnblogs.com/zltzlt-blog/p/17794029.html

相关文章

  • Qt之分裂器(QSplitter)
    一、QSplitter概述QSplitter是Qt中的一个布局管理器,允许用户在应用程序窗口中创建可拖动的分隔器,以便调整多个子窗口或控件的大小。它是一种非常有用的布局管理器,用于创建可分隔的多个部分,通常用于分割、重新排列和管理用户界面中的多个区域。以下是有关QSplitter的详细介......
  • Codeforces Round#905 解题报告
    按理来说最近开始了一天一套div2计划,第一天做了一套Div1,第二天做了hustfc,第三天因为要赶latex期末考试,所以什么也没做。明天写一下hustfc比较牛的几题。A暴力怎么做,是不是加加加,然后判断。B本质上是让长度为\(i\)的后缀全是\(0\)那么找到最短的有\(i\)个\(0\)......
  • Codeforces Round 904 (Div. 2)
    A.没想到是暴力,做的很晚B.手玩一下即可C.MediumDesign给定一个长为\(n\)的数组\(a\),和若干条线段\([l_i,r_i]\),你可以选择这其中的任何若干条线段,并让\(a_l\sima_r\)均\(+1\).请你计算可以得到的\(\max(a)-\min(a)\).这题本来想的是先把所有的加进去,得到......
  • 「题解」Codeforces Round 905 (Div. 3)
    before终于有一篇题解是一次性更所有题的了。A.MorningProblemA.MorningSol&Code根据题意模拟即可。#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT;int......
  • Codeforces 1786 / Codeforces Round #850 (Div.2)
    CodeforcesRound#850(Div.2)https://codeforces.com/contest/1786ProblemA1Non-alternatingDeck(easyversion)ProblemA2AlternatingDeck(hardversion)注意到最多进行\(O(\sqrtn)\)步,直接模拟即可。ProblemBCakeAssemblyLine题目保证了一定是\(n\)个蛋......
  • Codeforces Round 905 div2 F题
    记答案为\(ans_i\),表示从1到i次修改出现的字典序最小的数组a,\(c\)数组表示\(ans_i\)出现之后,所有修改的累加和。用一个vector存一下\(ans_i\)之后的所有修改。从1到q遍历每一次修改时,对\(c\)数组进行区间赋值操作,如果\(c\)数组中第一个不为0的数<0,那么\(ans_i\)加上\(c\)中的......
  • 「解题报告」Codeforces Round 653 (Div. 3)
    A.RequiredRemainderYouaregiventhreeintegers\(x,y\)and\(n\).Yourtaskistofindthemaximuminteger\(k\)suchthat\(0\lek\len\)that\(k\bmodx=y\),where\(\bmod\)ismodulooperation.Manyprogramminglanguagesusep......
  • Codeforces Round 905 (Div. 2)
    Preface周日晚上Div1,2,3同乐,但我不想打Div1,同时第三个号由于只打了两场没够到Div2的门槛,因此刚好打不了Div2,遂玩了一晚上LOL今天补了下这场题感觉难度偏低,E之前的题都比较签,F刚开始没想到转化成差分最小准备去写扫描线+线段树了,后面发现其实可以写的很简单A.Chemistry签,设......
  • CodeForces 946F Fibonacci String Subsequences
    洛谷传送门CF传送门duel的时候差点不会2400了。套路地,考虑每个\(F(x)\)中与\(s\)相同的子序列的贡献。设这个子序列为\(F(x)_{p_1},F(x)_{p_2},F(x)_{p_3},\ldots,F(x)_{p_n}\)。我们想要它成为一个子序列的子串,那么\(F(x)_{[p_1,p_n]}\)中除了\(p_1\simp_......
  • Codeforces 1862G 题解
    传送门题解因为有这个操作:将序列\(a\)加上\(\{n,n-1,\cdots,1\}\),考虑差分。那么显然每次操作会将差分数组中的每个元素减去\(1\),如果差分数组中有\(0\),就会把\(0\)删除。所以可以发现差分数组中剩下的一定是操作前的最大值。由于操作后最大值还是最大值,最小值仍......