首页 > 其他分享 >[COCI2009-2010#2] PASIJANS

[COCI2009-2010#2] PASIJANS

时间:2024-09-24 20:34:53浏览次数:1  
标签:return COCI2009 int top mid len 2010 PASIJANS id

[COCI2009-2010#2] PASIJANS

题意

给出 \(n\) 个栈,每次可从任意一个栈取出栈顶放入答案队列。

求字典序最小的答案队列。

思路

考虑贪心。每次从字典序最小的栈中取出栈顶。

如何动态找出字典序最小的栈?

可以使用堆,单次 \(O(1)\) 查找最小值,\(O(\log n)\) 插入。

但比较两个栈的字典序是 \(O(n)\) 的,如何优化?

可以使用哈希优化至 \(O(\log n)\)。

根据字典序的定义,字典序取决于两个字符串第一个不等的位置的关系。

只需使用二分找出第一个不等的位置,判断前缀是否相等使用哈希 \(O(1)\)。

这样总复杂度 \(O((\sum L) \log (\sum L) \log n\)。

特别地,当一个字符串是另一个字符串的前缀时,认为长度长的字典序小。

这样保证去掉这个后,接下来的操作最优。

代码

#include <bits/stdc++.h>
using namespace std;

using ull = unsigned long long;
using ui = unsigned int;
const int N = 2e3 + 5;

const ull Base = 10;
const ui Base2 = 4e9 + 7;
int n, a[N][N], L[N], top[N];
ull Hash[N][N], base[N];
ui Hash2[N][N], base2[N];

ull getHash(int id, int l, int len) {
	int r = l + len - 1;
	return Hash[id][r] - Hash[id][l - 1] * base[len];
}

ui getHash2(int id, int l, int len) {
	int r = l + len - 1;
	return Hash2[id][r] - Hash2[id][l - 1] * base2[len];
}

struct Int {
	int x;
};

bool cmp(int x, int y) {
	int lenX, lenY;
	lenX = L[x] - top[x] + 1;
	lenY = L[y] - top[y] + 1;
	int l = 1, r = min(lenX, lenY), mid, pos = -1;
	while (l <= r) {
		mid = (l + r) >> 1;
		if (getHash(x, top[x], mid) == getHash(y, top[y], mid)
		&& getHash2(x, top[x], mid) == getHash2(y, top[y], mid)) {
			l = mid + 1;
		} else {
			r = mid - 1;
			pos = mid;
		}
	}
	if (pos == -1) {
		return lenX > lenY;
	}
	return a[x][top[x] + pos - 1] < a[y][top[y] + pos - 1];
}

bool operator < (Int x, Int y) {
	return !cmp(x.x, y.x);
}

priority_queue <Int> Q; 

int main() {
	freopen("aaa.in", "r", stdin);
	freopen("aaa.out", "w", stdout);
	cin >> n;
	for (int i = 1; i <= n; i ++) {
		cin >> L[i];
		for (int j = 1; j <= L[i]; j ++) {
			cin >> a[i][j];
		}
		top[i] = 1;
	}
	base[0] = 1;
	for (int i = 1; i <= 2e3; i ++) {
		base[i] = base[i - 1] * Base;
	}
	base2[0] = 1;
	for (int i = 1; i <= 2e3; i ++) {
		base2[i] = base2[i - 1] * Base2;
	}
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= L[i]; j ++) {
			Hash[i][j] = Hash[i][j - 1] * Base + a[i][j]; 
		}
	}
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= L[i]; j ++) {
			Hash2[i][j] = Hash2[i][j - 1] * Base2 + a[i][j]; 
		}
	}
	for (int i = 1; i <= n; i ++) {
		Q.push({i});
	}
	while (!Q.empty()) {
		int id = Q.top().x;
		Q.pop();
		cout << a[id][top[id]] << " ";
		top[id] ++;
		if (top[id] > L[id]) {
			continue;
		}
		Q.push({id});
	}
	return 0;
}

标签:return,COCI2009,int,top,mid,len,2010,PASIJANS,id
From: https://www.cnblogs.com/maniubi/p/18429956

相关文章

  • 洛谷题单指南-分治与倍增-P3509 [POI2010] ZAB-Frog
    原题链接:https://www.luogu.com.cn/problem/P3509题意解读:n个点,每个点上有一只青蛙每次跳到距离自己第k近的点,m次之后跳到哪个点。解题思路:1、计算距离每个点第k近的点,存入ne[N]给定一个点i,距离i第k近的点一定在长度为k+1个点的窗口内,窗口包括i并且,第k近的点只能是左端点或者......
  • 题解:P5184 [COCI2009-2010#2] PASIJANS
    分析考虑贪心,每次尽量选最小的字符。显然是每次选字典序最小的弹栈。我们要比较的是每个栈的字典序,但是朴素比较是\(O(L)\)的,考虑将它优化到\(O(1)\)。这个时候我们可以先离散化然后套路地将所有串拼一起跑SA。记得在每个串之间加分割符。这样每次比较字典序就变成了\(......
  • 打卡信奥刷题(784)用Scratch图形化工具信P6488[普及组/提高组] [COCI2010-2011#6] OKUPL
    [COCI2010-2011#6]OKUPLJANJE题目描述一场巨大的派对结束以后,有五家报纸刊登了参加这场派对的人数,然而这些报纸上的数字可能是错误的。现在你知道整个会场的面积是LL......
  • D50 树的直径 P3629 [APIO2010] 巡逻
    视频链接: P3629[APIO2010]巡逻-洛谷|计算机科学教育新生态(luogu.com.cn)//两次DFS+树形DPO(n)#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;constintN=100005;intidx=1,head[N],to[N<<1],ne[N<<1],w[N<......
  • P2602 [ZJOI2010] 数字计数 题解
    数位dp的板子题?显然\([a,b]\)等价于\([0,b]-[0,a]\)。考虑\(dp_{i,j}\)表示到第\(i\)位数字\(j\)的答案。先不考虑数字大小限制(即1到999之类),则显然有\(dp_{i,j}=dp_{i-1,j}\times10+10^{i-1}。当前数字是0时则减去10^{i-1},再减去1。\)所以我们可以预处理出\(dp\),来表示后面......
  • LOJ#2885. 「SDOI2010」猪国杀
    对拍器在此。https://www.luogu.com/discuss/81283献忠!AC代码modoiread{usestd::{io::{stdin,Read},ops::{Add,Mul,Neg},};pubfnnext()->u8{letmuta=stdin().lock();letmutc=[0u8];matcha......
  • SBT20100VFCT-ASEMI低压降肖特基二极管SBT20100VFCT
    编辑:llSBT20100VFCT-ASEMI低压降肖特基二极管SBT20100VFCT型号:SBT20100VFCT品牌:ASEMI封装:ITO-220AB安装方式:插件批号:最新恢复时间:35ns最大平均正向电流(IF):20A最大循环峰值反向电压(VRRM):100V最大正向电压(VF):0.75V~0.95V工作温度:-65°C~150°C芯片个数:2芯片尺寸:mil正向浪涌电流(IFMS):180AS......
  • SBT20100VFCT-ASEMI低压降肖特基二极管SBT20100VFCT
    编辑:llSBT20100VFCT-ASEMI低压降肖特基二极管SBT20100VFCT型号:SBT20100VFCT品牌:ASEMI封装:ITO-220AB安装方式:插件批号:最新恢复时间:35ns最大平均正向电流(IF):20A最大循环峰值反向电压(VRRM):100V最大正向电压(VF):0.75V~0.95V工作温度:-65°C~150°C芯片个数:2芯片尺寸:mil正向浪......
  • P2048 [NOI2010] 超级钢琴
    P2048[NOI2010]超级钢琴题目链接其实这道题在我刚学oi两个月(2023.3)就见过了当时是作为st表的一个例题出现的,我学st表就已经学得迷迷糊糊的了,更别说这题了哈哈所以这是第二次见到他,必须写了(这一次他是作为NOIP模拟赛的一个部分分做法出现的)思路不错的限制:每......
  • CF 2010 C2. Message Transmission Error (hard version) (*1700) 字符串+哈希
    CF2010C2.MessageTransmissionError(hardversion)(*1700)字符串+哈希题目链接题意:给你一个字符串,让你判断是否是由某个字符串首尾拼接重叠而成的。思路:做法很多,最暴力就直接枚举字符串长度,然后哈希即可。代码:#include<bits/stdc++.h>usingnamespacestd;#def......