qbxt Day 5

Day 5

考试题解

T1 blocks

签到成功。

100分做法:

假设有三个序号分别为\(i\),\(i+1\),\(i+2\)的三个积木,那么可以分为两种情况讨论:\(i+1\)先和\(i\)相等或者\(i+2\)先和\(i+1\)相等。为什么不能\(i+2\)直接和\(i\)相等呢?

假设\(i+2\)直接和\(i\)相等,那么可以分为两种情况:1.\(i+1\)超过了\(i\),然后\(i+2\)\(i\)相等。但是这样的话,\(i+1\)会先与\(i\)持平。由于两块积木一直以1的差距缩小,所以肯定会出现相等的情况。2.\(i+1\)还没超过\(i+2\)。那么也就是说,\(i\)在和\(i+2\)持平的时候,已经超过了\(i+1\)。同理,因为\(i\)\(i+1\)每次高度也只缩小1,所以肯定会在\(i\)\(i+2\)持平之前就已经和\(i+1\)持平了。综上所述:\(i\)\(i+2\)持平时不可能是最优答案,那么答案就转化为了相邻两个积木的高度差(因为每次都缩短1,高度差即是时间)。将3块积木通过数学归纳法拓展,即可证明贪心结论正确。

考试时猜到了这个结论,但是没有严谨证明,直接口胡上然后拿暴力拍。拍过了之后知道结论没问题,所以其实考场上想到了结论可以直接写完拍,大不了拍出错再想别的。万一对了就赚大了。不用花费时间去证明。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,ans=1000000000;
ll h[100005];
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&h[i]);
	}
	for(int i=1;i<=n-1;i++){
		ans=min(ans,h[i]-h[i+1]);
	} 
	printf("%lld\n",ans);
	return 0;
}

T2 sort

80分做法:

优先队列,将前半个序列和后半个序列的值和下标分别存入优先队列,每次取出和插入,总时间复杂度为\(O(nlogn)\)考试时我就是这么写的,由于清北神机太快A了。。。

100分做法:

统计出前半部分排名在n/2名之后的和后一半排名在n/2之前的和相减即可。开longlong,时间复杂度O(n)。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long int ll;
ll n,a[500005],b[500005],sum1,sum2;
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	for(int i=1;i<=n/2;i++){
		if(a[i]>b[n/2]){
			sum1+=i;
		}
	}
	for(int j=n/2+1;j<=n;j++){
		if(a[j]<=b[n/2]){
			sum2+=j;
		}
	}
	printf("%lld\n",sum2-sum1);
	return 0;
}

T1和T2代码真的短,出题人好评

T3 string

30分做法:

指数级大爆搜。(我考试时就是这么打的,但是好像爆搜都打错了,全\(TLE\)了,30分白给)

60分做法:

区间\(dp\)

100分做法:

字典树:

T4 dinner

40分做法:

每次输入一段区间就将区间内的数全部标记为1,如果将两个存在矛盾的人都标记为了1,那么说明存在矛盾,否则则没有,时间复杂度为$O(

80分做法:

假设\(i\)\(j\)有矛盾,那么使用线段树维护与j有矛盾的最靠右的端点,然后每次判断一下

100分做法:

1.压位

2.40分+80分做法

数据结构

一般可得部分分。

优先队列

中位数

用两个优先队列维护,一个维护前一半,一个维护后一半。

线段树

支持单点修改,区间修改,单点查询,区间查询

树状数组

需要区间可合并并满足区间减法,用\([1,r]-[1,l]\)得到\([l,r]\)之间的答案。

ST算法

可交区间的合并。

Hotel

(好像做过)。用线段树维护左子树右端点向左的长度,维护右子树左端点向右的长度。

动态联通块

???????????????

Atlantis

给出\(n\)个矩形,求矩形的面积并。

扫描线法:

https://www.cnblogs.com/scau20110726/archive/2013/03/21/2972808.html

也可以用标记永久化来实现

思考题:

??????????????????????

Mishka and Interesting sum

??????????????????

莫队算法是什么?

Present

最小值最大问题做法一般都是二分答案。

如果一盆花

\(A\)数组进行差分得到\(B\)数组,\(A\)数组一段加上一个数,就相当于\(B\)数组中两个端点加上这个数。求前缀和就可以得到原数列。

hash表

映射的思想,与离散化类似。一般采用变为一个整数或者\(p\)进制然后对质数取%的方式,用\(vector\)存储较多,模数在10^6左右。

一般用来判重。

字符串HASH

\(p\)要大于字符串长度大小,双模数,一般值相同就大概率是相同的字符串。跟\(map\)类似,但时间复杂度更低。(https://www.cnblogs.com/zyf0163/p/4806951.html
https://blog.csdn.net/cindy_zhong/article/details/10465263

好处:可以代替很多字符串算法

如何用字符串\(Hash\)求最长连续回文串(\(manacher\)算法)

二分答案,从左到右枚举中心点,还要分奇偶两种情况讨论。

单调栈

栈内元素有单调性,一般作为工具在预处理数据的时候使用。

例题

决策单调性

方法:用栈来维护数据,由于决策单调性,新决策肯定由老决策转移而来,配合二分查找。如果新决策更优,那么全额抛弃老决策,因为它们不可能更优。反之,则从老决策中二分查找,找到最优决策,然后新决策进栈。

玩具装箱

写出\(n^2\)转移方程,仔细思考(打表)发现结果有单调性,所以使用单调栈优化。

Arr

假设选了所有\(a\)中的数,然后没有的数在不、中的第一次出现的位置是\(x\),在\(c\)中第一次出现的位置是\(y\),则有坐标\((x,y)\)

???????????????????????

分块

两种暴力相结合,从序列的第一个元素起,每连续\(S\)个元素组成一个块,总共分成\(n/S\)个块。

基本题

暴力1:维护前缀和,每次修改暴力\(O(n)\)修改前缀和,然后\(O(1)\)查询

暴力2:写出前缀和,然后用数组记录下每一次修改,这样修改是\(O(1)\),但是查询是\(O(m)\)

中和两种方法:

莫队

posted @ 2020-10-05 23:58  徐明拯  阅读(82)  评论(0编辑  收藏  举报