【Luogu1638】逛画展

点此进入原题

算法:(有技巧的)模拟

题解

这题可以不用真实的队列,只要用两个变量模拟一下就可以啦

也可以说是枚举的思想:这题很容易想到O(n^2)的枚举区间的算法,容易TLE。先找到第一个包含所有不同数字的区间[i,j],然后让i+1,同时枚举j找到另一个区间,然后取j-i的最小值就OK辣。判断不同的数字完全可以用桶解决

可能我的语文差了一点,具体看我的代码吧(好难表述啊QAQ)

代码

#include<cstdio>
const int N=1000005,M=2017;
int a[N],b[M],n,m,l,r=1<<30;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1,j=0,k=0;i<=n;i++) //枚举区间[i,j]
    {
        while(k<m) //枚举j找到包含m个不同元素的区间[i,j].(k表示不同的数的个数)
        {
            j++; //小细节:j初值为0,提前自增,避免了一些麻烦
            if(j>n) break;
            if(b[a[j]]==0) k++; //此数未出现过,k++
            b[a[j]]++;
        }
        if(k==m&&r-l>j-i) l=i,r=j; //修改最小值
        b[a[i]]--; //i+1前将第i个数移出区间
        if(b[a[i]]==0) k--; //如果此数在[i,j]中只出现一次并且现在被移出,那么k--
    }
    printf("%d %d",l,r); //最后输出答案区间,结束~
}
时间: 2024-10-13 15:06:01

【Luogu1638】逛画展的相关文章

逛画展

洛谷P1638 逛画展 很经典的一道类似有一个头,一个尾,然后头和尾移动,从前往后扫一遍的题,我以前做过一道类似的,很相似,不过我不记得了,唉,可惜.正解是枚举区间的左右端点,右端点不断移动直到正好框住k种,此时,(r-l)与(j-i)比较,更新l,r,最后i++,直到i==n. 我一开始也没想到这样枚举,我想的是枚举框的长度,这样从小到大枚举,每次扫一遍判断是否包含k个,A了4个点,剩下的都TLE了... #include<bits/stdc++.h> using namespace std

洛谷P1638 逛画展

P1638 逛画展 1 #include <bits/stdc++.h> 2 #define LL long long 3 #define For(i,j,k) for(int i=j;i<=k;i++) 4 using namespace std ; 5 6 const int N = 1000011 ; 7 int n,m,ansl,ansr,le,ri ; 8 int a[N],f[2011] ; // 9 10 inline int read() 11 { 12 int x =

P1638 逛画展(直尺法)

这道题是直尺法的模板题: #include<iostream> using namespace std; const int maxn = 1e6 + 5; const int M = 2e3 + 5; int n, m, a[maxn], vis[M]; int main(){ cin >> n >> m; for (int i = 0; i < n; ++i)cin >> a[i]; int st = 0, en = 0, num = 0, res

luogu_P1638 逛画展

尺取法,先右挪右端点,可以了就挪左端点至不行,然后又挪右端点,一直一直一直这样子 #include<iostream> #include<cstdio> #define ri register int #define u int namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } whil

单调队列,单调栈相关

说起这个话题,应该很多人会有一种似有所悟,但又不敢确定的感觉. (我差不多就是那样) 没错,这正是因为其中“单调”一词的存在. 那么单调是什么? 学过函数的人都知道单调函数或者函数的单调性吧 其实直白一点说单调,就是一直增或一直减. eg:1,3,5,9就是一个单调增数列,数列中不存在后一个数比前一个数小的现象. 那么同样,在这里谈到的话题也有类似特点. (一)单调队列 其实就是一个符合单调性质的队列,但它同时具有单调的性质以及队列的性质. 使用频率不算高,但却占有至关重要的地位.它的作用很简单

Luogu P1083 借教室【二分答案/差分】By cellur925

题目描述 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份 订单,每份订单用三个正整数描述,分别为dj, sj, tj,表示某租借者需要从第sj天到第tj天租 借教室(包括第sj天和第tj天),每天需要租借dj个教室. 我们假定

单调队列/单调栈入门详解+题目推荐

以前一直以为这两个是很高级的东西,这段时间用到了才开始学,发现实际上非常简单 下面我们以单调队列为例进行讲解,单调栈自行类比 顾名思义 单调队列这个名字就指明了它的性质--单调性 我们来看一道例题--滑动窗口 题面在此不再赘述,大意就是有一个长度为\(n\)的数列,一个长度为\(k\)的窗口,输出窗口位于每个位置下的下的最大最小值 嗯,题目很好理解,st表或者线段树过的先别说话,我们来看看另一种方法 我们维护一个长度为k的队列,使得队列的开头为答案,那么我们每次只需要输出开头就好了.这个想法很好

51nod:1689 逛街

原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1689 一开始想枚举逛街的终点,然后开两个大根堆维护b值,分别保证喜爱店不少于k,以及在此前提下逛到的店尽可能多.具体实现是维持第一个堆元素数为k,每加入一个元素,如果c为1,就丢进第一个堆,并把堆顶丢到第二个,c为0直接丢进第二个.如果两个堆的元素b值之和超过T,就从第二个堆删元素. 但是这种写法最后的删元素部分有可能删去对答案有贡献的点,这时再把丢掉的元素

3304 水果姐逛水果街Ⅰ

3304 水果姐逛水果街Ⅰ 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 水果姐今天心情不错,来到了水果街. 水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样. 学过oi的水果姐迅速发现了一个赚钱的方法:在某家水果店买一个水果,再到另外一家店卖出去,赚差价. 就在水果姐窃喜的时候,cgh突然出现,他为了为难水果姐,给出m个问题,每个问题要求水果姐从第