这是一个神奇的课题,其实我觉得用一个词来形容这个算法挺合适的:暴力。

是啊,就是循环+暴力。没什么难的。。。

先来看一道裸题。

那么对于这道题,显然我们的暴力算法就是枚举区间的左右端点,然后通过前缀和统计结果。时间复杂度O(n^2),但是如果我们的数据范围到了100000,那么我们的算法就T了。

于是我们考虑一个性质。如果我们发现一个区间,这个区间的sum<k,那么被这个区间包含的区间都不可能是答案。

所以我们用两个指针(左右端点。)如果目前区间的sum<k,我们就延伸右端点。否则我们就统计答案,然后让左端点往右移。直到2个指针都到达n,结束枚举。

这显然很水对吧。

那么我们来一道稍难的问题。

那么我们先想一下我们的策略,假如我们把所有的区间按照区间长度排序,那么我们的答案一定是其中的连续一段区间。因为跳着取肯定没有连着取更优。

那么我们接下来就是判断区间的覆盖次数了。显然我们可以用线段树轻松解决这个问题。

说起来挺简单,其实实现起来还是挺复杂的。

下面贴上代码

#include<cstdio>
#include<algorithm>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define ls (k<<1)
#define rs (k<<1|1)
#define M 500005
#define MN 1<<20
#define inf 0x3f3f3f3f
using namespace std;
int n,m,cnt,l[M],r[M],rk[M],val[M<<],t[MN<<],ans=inf,mark[MN<<],len[M];
int find(int x){
int le=,re=cnt;
while(le<re){
int mid=le+re>>;
if(val[mid]<x)le=mid+;
else re=mid;
}return le;
}
void pushdown(int k){mark[ls]+=mark[k],mark[rs]+=mark[k],t[ls]+=mark[k],t[rs]+=mark[k],mark[k]=;}
void fpush(int k){t[k]=max(t[ls],t[rs]);}
void update(int l,int r,int a,int b,int k,int ad){
if(a<=l&&r<=b){mark[k]+=ad;t[k]+=ad;return;}if(l!=r&&mark[k])pushdown(k);int mid=l+r>>;
if(a<=mid)update(l,mid,a,b,ls,ad);
if(b>mid)update(mid+,r,a,b,rs,ad);
fpush(k);
}
bool cmp(int a,int b){return len[a]>len[b];}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d%d",&l[i],&r[i]),len[i]=r[i]-l[i],rk[i]=i,val[i<<]=l[i],val[i<<|]=r[i];
sort(val+,val+(n<<)+);sort(rk+,rk+n+,cmp);
for(int i=;i<=(n<<)+;i++)if(val[i-]!=val[i])val[++cnt]=val[i];
for(int i=;i<=n;i++)l[i]=find(l[i]),r[i]=find(r[i]);
for(int le=,re=;le<=n;le++)
for(update(,cnt,l[rk[le]],r[rk[le]],,);t[]>=m;re++){
update(,cnt,l[rk[re]],r[rk[re]],,-);
ans=min(len[rk[re]]-len[rk[le]],ans);
}
printf("%d\n",ans==inf?-:ans);
}

————————————————我是分割线————————————————

第一块讲完啦!接下来第二块。

矩阵快速幂=矩阵+快速幂。。

我记得我讲过。。但是博客不见了⌇●﹏●⌇吓死宝宝惹

无奈的重讲一遍。

首先我们要了解一下矩阵。。(虽然我们夏令营的时候讲过,但是显然向量内积什么的特别难理解,所以我们不要管理念)

总之就是n*m个数的集合。

然后我们理解一下矩阵乘法的定义

直接上图

那么我们用矩阵乘法解决什么问题呢?

答:dp问题。

是不是很奇怪?

但是其实并不难理解、

我们举个例子。

假设我们已知DP式子:dp[i]=dp[i-1]+dp[i-2],假如我们想要直接得到dp的第n项,而且n的值特别大,比如10^18,那么显然我们不能On推过去。

那怎么办呢?我们可以把dp方程转移为一个矩阵。

那么我们得到的这个矩阵表示,假如说我们把矩阵的第一位变为矩阵的第二位和矩阵的第三位之和,把矩阵的第二位变为矩阵的第一位,矩阵的第三位变为矩阵的第二位。

由于每次的转移方程都不变,所以我们只要把这个矩阵做快速幂就好了。

是不是很简单?

下面贴上例题&&代码

代码:

#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define MOD 1000000007
struct mat
{
int z[][];
mat(){memset(z,,sizeof(z));}
mat operator*(mat b)
{
mat c;int i,j,k;
for(i=;i<;++i)for(j=;j<;++j)
for(k=;k<;++k)c.z[i][j]=(c.z[i][j]+(ll)z[i][k]*b.z[k][j])%MOD;
return c;
}
}f,x;
mat pow(ll x)
{
mat r=f,t=f;
for(--x;x;x>>=,t=t*t)if(x&)r=r*t;
return r;
}
int main()
{
ll n;
f.z[][]=f.z[][]=f.z[][]=;
x.z[][]=x.z[][]=;
scanf("%lld",&n);
printf("%d",(x*pow(n-)).z[][]);
}

培训补坑(day10:双指针扫描+矩阵快速幂)的更多相关文章

  1. 矩阵快速幂/矩阵加速线性数列 By cellur925

    讲快速幂的时候就提到矩阵快速幂了啊,知道是个好东西,但是因为当时太蒟(现在依然)没听懂.现在把它补上. 一.矩阵快速幂 首先我们来说说矩阵.在计算机中,矩阵通常都是用二维数组来存的.矩阵加减法比较简单 ...

  2. Codeforces Round #536 (Div. 2) F 矩阵快速幂 + bsgs(新坑) + exgcd(新坑) + 欧拉降幂

    https://codeforces.com/contest/1106/problem/F 题意 数列公式为\(f_i=(f^{b_1}_{i-1}*f^{b_2}_{i-2}*...*f^{b_k} ...

  3. hdu 2604 Queuing dp找规律 然后矩阵快速幂。坑!!

    http://acm.hdu.edu.cn/showproblem.php?pid=2604 这题居然O(9 * L)的dp过不了,TLE,  更重要的是找出规律后,O(n)递推也过不了,TLE,一定 ...

  4. poj 3735 Training little cats(矩阵快速幂,模版更权威,这题数据很坑)

    题目 矩阵快速幂,这里的模版就是计算A^n的,A为矩阵. 之前的矩阵快速幂貌似还是个更通用一些. 下面的题目解释来自 我只想做一个努力的人 @@@请注意 ,单位矩阵最初构造 行和列都要是(猫咪数+1) ...

  5. Luogu P3390 【模板】矩阵快速幂&&P1939 【模板】矩阵加速(数列)

    补一补之前的坑 因为上次关于矩阵的那篇blog写的内容太多太宽泛了,所以这次把一些板子和基本思路理一理 先看这道模板题:P3390 [模板]矩阵快速幂 首先我们知道矩阵乘法满足结合律而不满足交换律的一 ...

  6. HDU1005 找规律 or 循环点 or 矩阵快速幂

    http://acm.hdu.edu.cn/showproblem.php?pid=1005 1.一开始就注意到了n的数据范围 <=100 000 000,但是还是用普通的循环做的,自然TLE了 ...

  7. 【BZOJ5505】[GXOI/GZOI2019]逼死强迫症(矩阵快速幂)

    [BZOJ5505][GXOI/GZOI2019]逼死强迫症(矩阵快速幂) 题面 BZOJ 洛谷 题解 如果没有那两个\(1*1\)的东西,答案就是斐波那契数,可以简单的用\(dp\)得到. 大概是设 ...

  8. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  9. cf352E Jeff and Brackets dp+矩阵快速幂(加法+min运算)

    题意大致是这样的,一共要放 m 段括号序列,每一段放 n 个括号,也就是放 n*m个括号,再每一段中的 n 个位置分别有放左括号和右括号的代价,问最终摆放出合法的括号序列的最小代价是多少. 另外保证, ...

随机推荐

  1. 【vim环境配置】解决ubuntu上 由YouCompleteMe插件配置不当引起的 自动补全失效的问题

    背景: 由于不可抗拒的原因,学习环境由之前centos的一台机器上,变成了ubuntu的一台机器上.因此,需要在新的ubuntu的机器上再配置一次vim环境.算起来这已经是第三次配置vim环境了(ma ...

  2. C#操作Excel文件(转)

    摘要:本文介绍了Excel对象.C#中的受管代码和非受管代码,并介绍了COM组件在.net环境中的使用. 关键词:受管代码:非受管代码:Excel对象:动态连接库 引言 Excel是微软公司办公自动化 ...

  3. Qt Qwdget 汽车仪表知识点拆解1 速度表示

    先贴上效果图,注意,没有写逻辑,所以这些都是乱动的 这里线主要说一下中间显示速度的显示制作的方式,在这里,自己专门写了一个数字的仪表 考虑的一般的汽车是没有办法把瞬时速度提升到四位数的,所以我这里就放 ...

  4. 阿里云SLB上http强制跳转到https问题处理

    背景: 最近一客户有一个需求,需要将外网所有http访问请求强制跳转到https,公网出口使用阿里云SLB,证书放在SLB上,SLB后端实例为ECS(webserver)web服务使用nginx, 网 ...

  5. spring boot 线程池配置

    1.配置类 package cn.com.bonc.util; import java.util.concurrent.Executor; import java.util.concurrent.Th ...

  6. C++ STL容器——stack用法介绍

    stack是一种容器适配器,专门设计用于在LIFO上下文中操作(后进先出),其中元素仅从容器的一端插入和删除. 容器适配器,而不是一种容器. 它是容器适配器是指,只要支持一系列方法的容器(empty, ...

  7. 剑指offer-旋转数组的最小数字06

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...

  8. 数据挖掘算法:DBSCAN算法的C++实现

    (期末考试快到了,所以比较粗糙,请各位读者理解..) 一.    概念 DBSCAN是一种产生划分聚类的基于密度的聚类算法,簇的个数由算法自动地确定.低密度区域中的点被视为噪声而忽略,因此DBSCAN ...

  9. [boost-2] 智能指针

    boost库学习: 智能指针: shared_ptr指针,定义在boost::shared_ptr,如果开发环境支持的话,可以使用memory中的std::shared_ptr. shared_ptr ...

  10. servlet入门(1)

    第一个servlet类 1.编写一个java类,继承HttpServlet类 2.重写doget和dopost方法 3.Servlet程序在tomcat服务器运行 第一步:找到server窗口,并新建 ...