首页 > 其他分享 >闲话 Day3

闲话 Day3

时间:2023-04-23 19:46:32浏览次数:49  
标签:lf ps sz int 闲话 复杂度 Day3 reload

今天上来决定开始打 数颜色
看算法标签,带个分块莫队,而且之前见的时候也是在分块专题。

看题,十分钟过去。。。。。

发现有 \(O(n \log^2 n)\) 时间,\(O(n)\) 空间的 CDQ 做法,显然严格优于带修莫队啊。
翻了翻题解,前面的有一个 \(O(n \log n)\) 空间的树套树,然后几乎全是分块莫队。
然后我就想,为啥都不写 CDQ 呢。
于是我决定打一个出来。

这就是为什么我这一个上午 + 一个下午啥都没干。
现在已经打了 233 行了,还差一部分没打。
而且打着打着也就意识到,这东西常数确实大到飞起。
另外,这么复杂的东西,如果是在考场上,我可能也需要考虑考虑是否要打。
仔细想想,其实综合来看不如带修莫队。

事实上,我之前做题写代码的习惯一直都是,尽可能使用复杂度更优秀的算法/实现方式。
现在,遇到的题越来越复杂,码力的提升速度远远比不上题目难度的增长。
况且,对于一些题目,相对于思考做法,打代码消耗的时间往往会更长。

所以,我们来考虑另一样东西吧,代码复杂度。
毕竟码力是有限的,不能抛开实现只考虑渐进复杂度。
即使时间无限,写的代码更长也意味着调试的时间更长,心态更爆炸。
如何在保证时空复杂度的前提下降低实现难度,是应该仔细考虑的。

文艺平衡树

写闲话写一半又回去做了个题。
treap 确实很好写啊。
但是我不喜欢平衡树。我也不知道为啥反正莫名其妙不喜欢。
所以我们来根号分治吧。

具体的,维护连续段。
每次分裂 \(O(1)\) 个连续段,然后把一段区间直接暴力翻转。
当连续段数量超过 \(O(\sqrt n)\) 的时候就把贡献直接统计到序列上,然后把连续段变回一个。
复杂度 \(O(n \sqrt n)\),常数不大,实现难度肉眼可见的小。
而且跑的确实非常快,内存也很小。
重点是不需要任何的算法或者数据结构,简直就是普及组实现难度。
当然,这东西的优越性主要体现在调试难度上。

给一个仍然有点冗长的代码吧。

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define sz 100005
struct site
{
	int lf, rt, x, y;
	site(){}
	site(int a, int b, int c, int d)
	{
		lf = a; rt = b;
		x = c; y = d;
	}
};
site ps[sz];
int n, m, big, top = 1;
int num[sz], tmp[sz];
void split(int, int);
void reload();
int main()
{
	int x, y, savx, savy;
	scanf ("%d %d", &n, &m);
	big = sqrt(m) * 0.8;
	for (int i = 1; i <= n; ++i)
		num[i] = i;
	ps[1] = site(1, n, 1, n);
	for (int i = 1; i <= m; ++i)
	{
		scanf ("%d %d", &x, &y);
		savx = x; savy = y;
		for (int j = 1; j <= top; ++j)
		{
			if (ps[j].lf < x && ps[j].rt >= x)
				split(j, x);
			if (ps[j].lf <= y && ps[j].rt > y)
				split(j, y + 1);
		}
		for (int j = 1; ; ++j)
			if (ps[j].lf <= x && ps[j].rt >= x)
			{
				x = j;
				for ( ; ; ++j)
					if (ps[j].lf <= y && ps[j].rt >= y)
					{
						y = j;
						break;
					}
				break;
			}
		for (int j = x, k = y; j < k; ++j, --k)
			swap(ps[j], ps[k]);
		for (int j = x; j <= y; ++j)
		{
			swap(ps[j].x, ps[j].y);
			ps[j].lf = savy - (ps[j].lf - savx);
			ps[j].rt = savy - (ps[j].rt - savx);
			swap(ps[j].lf, ps[j].rt);
		}
		if (top > big)
			reload();
	}
	reload();
	for (int i = 1; i <= n; ++i)
		printf ("%d ", num[i]);
	return 0;
}

void split(int a, int b)
{
	if (ps[a].x < ps[a].y)
	{
		ps[++top] = site(b, ps[a].rt, ps[a].x + b - ps[a].lf, ps[a].y);
		ps[a].y = ps[a].x + b - ps[a].lf - 1;
	}else
	{
		ps[++top] = site(b, ps[a].rt, ps[a].x - b + ps[a].lf, ps[a].y);
		ps[a].y = ps[a].x - b + ps[a].lf + 1;
	}
	ps[a].rt = b - 1;
	for (int i = top; i > 1; --i)
	{
		if (ps[i].lf > ps[i - 1].lf)
			break;
		swap(ps[i], ps[i - 1]);
	}
}

void reload()
{
	for (int i = 1; i <= n; ++i)
		tmp[i] = num[i];
	for (int i = 1; i <= top; ++i)
		if (ps[i].x < ps[i].y)
			for (int j = ps[i].lf, k = ps[i].x; j <= ps[i].rt; ++j, ++k)
				num[j] = tmp[k];
		else
			for (int j = ps[i].lf, k = ps[i].x; j <= ps[i].rt; ++j, --k)
				num[j] = tmp[k];
	top = 1;
	ps[1] = site(1, n, 1, n);
}

沾点学术就够了。后面开始发电。


进行这种思考和尝试,也许是心态的变化吧。
之前学 OI 的时候完全是抱着学术的心态,想要追求更加优秀的算法,多见一些有意思的东西。
所以当时学了不少例如线性RMQ、HLPP之类的冷门东西。

至于现在的话。。。
我确实已经好久没有学新东西了。
最开始学 OI 的时候确实可以抱着“只是来提升一下思维水平,感觉比文化课有意思”之类的理由。
现在目的基本上达到了。尤其是第二个。
但是,已经用掉了两年了。
只能说,空着手回去的话确实很亏。
具体原因的话。。。

无论什么东西,只要沾了考试,就难免被功利化和套路化。
高考就是一个很极端的例子。
老师学生苦心钻研的做题技巧,对于这个学科本身毫无帮助。只不过是应付考试罢了。
这也许是我不太喜欢文化课的原因之一吧。
我整体上还是倾向于纯粹的学术之类的。

初中的时候甚至没有听说过算法这个词,当时计划着以后去学物理。
然后被高中物理干碎了。
其实说白了,除了模拟计算就是模拟计算。用的是草稿纸,干的是电脑的活。

了解的越来越多之后才知道,HE 的这种现象比其他地区要明显很多。
毕竟在经济上是弱省,思想上比较保守,教育水平当然上不去。
也就 hz 这么个地方,看似闭塞,但是确实可以很大程度的了解外面。

以前经常会埋怨学校。
但是现在看,HE 出来这么个学校倒也合理。
想要在这么个地方和其他强省比,显然是需要代价的。
当然,学校该骂还是要骂,确实NT。

如果只是想安稳的生活的话,其实我家附近就很好。
工作压力不算大,没有加班一类的事情。
只要不浪费,挣的钱够用,生活大概是很安逸的。

但是我不是这么个喜欢安稳的人啊。至少现在不是。

想要个人发展,肯定不能在这么个地方。
在 HE 学奥赛,对思维水平一类的帮助大概是没有其他地方要大的。
毕竟教练也说了,靠的是暴力走天下。

所以,就不得不功利化一点了。
至少,先见一见外面的世界吧。


麻麻省的今天怎么写了这么多。
反正也没啥需要隐晦的,该写的都写了吧。

标签:lf,ps,sz,int,闲话,复杂度,Day3,reload
From: https://www.cnblogs.com/-Houraisan-Kaguya/p/17347518.html

相关文章

  • day39| 62+63
    62.不同路径 题目简述:一个机器人位于一个mxn 网格的左上角(起始点在下图中标记为“Start”)。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。问总共有多少条不同的路径? 思路:1.到每个网格都有对应路径数2.假设到......
  • day37| 738+968
    738.单调递增的数字 题目简述:当且仅当每个相邻位数上的数字 x 和 y 满足 x<=y 时,我们称这个整数是单调递增的。给定一个整数n,返回小于或等于n的最大数字,且数字呈单调递增。 思路:1.记ns[i]表示数字n从高到低的第i位的数字,i从0开始2.从左到右寻找,找到的......
  • day36| 435+763+56
    435.无重叠区间 题目简述: 给定一个区间的集合 intervals ,其中intervals[i]=[starti,endi] 。返回需要移除区间的最小数量,使剩余区间互不重叠 。 思路:利用昨天题目452的思路即可 代码:classSolution:deferaseOverlapIntervals(self,intervals:Lis......
  • day35| 860+406+452
    860.柠檬水找零 题目简述:在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付5美元、10美元或20美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付5美元。注意......
  • 闲话 Day2
    今日份的闲话。接着凑数,写点比较显然的东西。通过日常做题可以观测到一些现象:上午做题效果明显好于下午(由通过的题目数量及难度统计得到)。如果模拟赛都是神仙题,则改完之后晚上非常困。摆烂一整天之后晚上几乎不困。不妨建立一个模型,每个人会存在一个值。叫什么呢,就叫脑......
  • 初学者代码训练Day3(c/c++)
    题目中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱百鸡问题”:一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱,现在要用百钱买百鸡,请问公鸡、母鸡、小鸡各多少只? 流程图: 代码:1#include<iostream>2usingnamespacestd;3intmain()4{intgongji,mu......
  • redis高级-day3——GEO地理位置信息
    目录1GEO地理位置信息1GEO地理位置信息#GEO(地理信息定位):存储经纬度,计算两地距离,范围等 -根据经纬度---》确定具体地址的---》高德开放api---》返回具体地址#redis可以存储经纬度,存储后可以做运算, 比如:两个经纬度之间距离(直线距离)比如:统计某个经纬度......
  • 闲话:如何发电
    闲话:如何发电搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪有不疯的?搞OI哪......
  • T-SQL基础教程Day3
    第三章联接3.1交叉联接交叉联接是最简单的联接类型。交叉联接仅执行一个逻辑查询处理阶段——笛卡尔乘积将一个输入表的每一行与另一个表的所有行匹配SQLServer支持交叉联接的两种标准语法:ANSISQL-92和ANSISQL-89语法,建议使用ANSISQL-92语法3.1.1ANSISQL-92语法SELECTC.cu......
  • day32| 122+55+45
    122.买卖股票的最佳时机 给你一个整数数组prices,其中 prices[i]表示某支股票第i天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有一股股票。你也可以先购买,然后在同一天出售。返回你能获得的最大利润 。 思路:1.可以当......