首页 > 其他分享 >P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III

P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III

时间:2023-12-07 10:15:24浏览次数:38  
标签:Ynoi2019 cur P5048 int tot rg ans include III

题意

给定序列 \(s\),每次询问 \(l, r\) 的区间众数的出现次数。

强制在线。空间:\(62.5MB\)。

Sol

蒲公英卡常卡空间版。

考虑优化那个 \(n \times m\) 的数组。

我们要求 \(l, r\) 之中某个数的个数。

乍一看不好弄,仔细想想就会发现,如果我们知道当前的最优答案。在长常数时间内就能知道当前散块是否比最优答案更优。

考虑将每个数按照下标扔进 \(n\) 个 \(vector\)。

直接暴力查询 \(p_x + ans\) 即可。

不难发现,该算法的时间复杂度是正确的。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <queue>
#include <vector>
#include <cassert>
#define pii pair <int, int>
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
	int p = 0, flg = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') flg = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		p = p * 10 + c - '0';
		c = getchar();
	}
	return p * flg;
}
void write(int x) {
	if (x < 0) {
		x = -x;
		putchar('-');
	}
	if (x > 9) {
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

#define rg register
#define il inline

#define fi first
#define se second

const int N = 5e5 + 10, M = 1505;

array <int, N> s, h;

namespace Blk {

int bsi = 433;

il int calc(rg int x) {
	return (x - 1) / bsi + 1;
}

array <int, N> cur;
queue <int> q;
int tot;

il void add(rg int x, rg int y) {
	if (!x) return;
	cur[x] += y;
	q.push(x);
	if (cur[x] > cur[tot]) tot = x;
	else if (cur[x] == cur[tot]) tot = min(tot, x);
}

il void clear() {
	while (!q.empty())
		cur[q.front()] = 0, q.pop();
	tot = 0;
}

array <array <pii, M>, M> isl;
array <vector <int>, N> suf, pre;

array <int, N> idx, dfn;

il void init(rg int n) {
	for (rg int i = 1; i <= calc(n); i++) {
		for (rg int j = i; j <= calc(n); j++) {
			for (rg int k = (j - 1) * bsi + 1; k <= min(j * bsi, n); k++)
				add(s[k], 1);
			isl[i][j] = make_pair(tot, cur[tot]);
		}
		clear();
	}
	for (rg int i = 1; i <= n; i++)
		suf[s[i]].push_back(i), dfn[i] = suf[s[i]].size() - 1;
	for (rg int i = n; i >= 1; i--)
		pre[s[i]].push_back(i), idx[i] = pre[s[i]].size() - 1;
}

il int query(rg int x, rg int y) {
	if (abs(calc(x) - calc(y)) <= 1) {
		for (rg int i = x; i <= y; i++)
			add(s[i], 1);
		rg int ans = cur[tot]; clear();
		return ans;
	}
	rg int ans, tot; tie(tot, ans) = isl[calc(x) + 1][calc(y) - 1];
	for (rg int i = x; i <= calc(x) * bsi; i++) {
		while ((int)suf[s[i]].size() > ans + dfn[i] && suf[s[i]][ans + dfn[i]] <= y)
			ans++, tot = s[i];
		/* assert(ans + dfn[i] - 1 >= 0); */
		/* if ((int)suf[s[i]].size() > ans + dfn[i] - 1 && suf[s[i]][ans + dfn[i] - 1] <= y) */
			/* tot = min(tot, s[i]); */
	}
	for (rg int i = (calc(y) - 1) * bsi + 1; i <= y; i++) {
		while ((int)pre[s[i]].size() > ans + idx[i] && pre[s[i]][ans + idx[i]] >= x)
			ans++, tot = s[i];
		/* assert(ans + idx[i] - 1 >= 0); */
		/* if ((int)pre[s[i]].size() > ans + idx[i] - 1 && pre[s[i]][ans + idx[i] - 1] >= x) */
			/* tot = min(tot, s[i]); */
	}
	/* write(ans), puts("@"); */
	return ans;
}


}

signed main() {
	/* freopen("P4168_2.in", "r", stdin); */
	rg int n = read(), m = read();
	for (rg int i = 1; i <= n; i++)
		s[i] = h[i] = read();
	/* sort(h.begin() + 1, h.begin() + 1 + n); */
	/* rg int k = unique(h.begin() + 1, h.begin() + 1 + n) - h.begin() - 1; */
	/* for (rg int i = 1; i <= n; i++) */
		/* s[i] = lower_bound(h.begin() + 1, h.begin() + 1 + k, s[i]) - h.begin(); */
	rg int lst = 0;
	Blk::init(n);
	while (m--) {
		rg int l = read(), r = read();
		l = (l ^ lst), r = (r ^ lst);
		/* l = (l + lst - 1) % n + 1, r = (r + lst - 1) % n + 1; */
		if (l > r) swap(l, r);
		write(lst = Blk::query(l, r)), puts("");
	}

	return 0;
}

标签:Ynoi2019,cur,P5048,int,tot,rg,ans,include,III
From: https://www.cnblogs.com/cxqghzj/p/17881048.html

相关文章

  • SP1716 GSS3 - Can you answer these queries III 题解
    题意:给定一个长度为$n$的序列$a$,$q$次操作,每次操作为以下之一:\(0\)\(x\)\(y\):将\(a_x\)修改为\(y\)\(1\)\(l\)\(r\):询问区间\([l,r]\)的最大连续子序列和思路:考虑线段树维护区间最大连续子序列和:线段树每个节点需要维护的信息:区间左端点$l$,区......
  • 代码随性训练营第四十八天(Python)| 198.打家劫舍、213.打家劫舍II、337.打家劫舍 III
    198.打家劫舍1、动态规划classSolution:defrob(self,nums:List[int])->int:#dp数组代表在第i个房间可以偷窃到的最高金额为dp[i]dp=[0]*len(nums)iflen(nums)==1:returnnums[0]iflen(nums)==2:......
  • SP19543 GSS8 - Can you answer these queries VIII 题解
    更好的阅读体验SP19543GSS8-CanyouanswerthesequeriesVIIIfhq+二项式定理。提供一个不太一样的思路。默认下标从\(1\)开始。首先插入删除,区间查询,想到可以平衡树维护或者离线下来做线段树。本文中是用的是fhq,好写一些。\(k\)非常的小,考虑对于每一个\(k\)的答......
  • 普冉PY32系列(十二) 基于PY32F002A的6+1通道遥控小车III - 驱动篇
    目录普冉PY32系列(一)PY32F0系列32位CortexM0+MCU简介普冉PY32系列(二)UbuntuGCCToolchain和VSCode开发环境普冉PY32系列(三)PY32F002A资源实测-这个型号不简单普冉PY32系列(四)PY32F002A/003/030的时钟设置普冉PY32系列(五)使用JLinkRTT代替串口输出日志普冉P......
  • 123. 买卖股票的最佳时机 III(难)
    目录题目动态规划题目给定一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。示例1:输入:prices=[3,3,5,0,0,3,1,4]输出:6......
  • 勘误《新概念》III
    ----------------------------BookIII朗文外研社新概念英语(新版)1997年10月第一版2005年7月第36次印刷ISBN7-5600-1348-1责任编辑:(朗文)王德厚梅丹心(外研社)孙蓓任小玫----------------------------错误编号      出现页码         ......
  • P-III曲线水文频率计算程序(方法)
    P-III曲线水文频率计算程序(方法) 最近遇到水文频率曲线拟合计算相关的问题,在网上查阅了一下,毕竟是专业性比较强的知识内容,好像没有比较系统全面的资料,一时兴起,做了一些研究,总结了一下所了解的一些计算方法以及能够帮助我们解决实际问题的辅助计算软件,并作了对比分析,主要情况如下......
  • 代码训练营第二十五天(Python)| 216.组合总和III 、17.电话号码的字母组合
    216.组合总和IIIclassSolution:defcombinationSum3(self,k:int,n:int)->List[List[int]]:res=[]self.tracebacking(n,k,1,0,[],res)returnresdeftracebacking(self,targetsum,k,start,now_sum,path,res):......
  • [vue]精宏技术部试用期学习笔记 III
    精宏技术部试用期学习笔记(vue)父子通信什么是通信/为什么要通信通信即在不同组件之间传输数据当在复用组件时,需要传递不同数据达成不同的表现效果能够根据其他组件的行动,响应式的做出变化Props功能:让父组件信息传递到子组件code:假定index.vue已经通过rou......
  • 【算法题】只出现一次的数字 III
    题目:给你一个整数数组nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。你可以按任意顺序返回答案。你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。示例1:输入:nums=[1,2,1,3,2,5]输出:[3,5]解释:[5,3]也是......