P1440 求m区间内的最小值
提供一个比较清奇的思路 第一次想出和题解不一样的思路,好激动
看到题解都是大佬再秀,自认为我的思路好理解一些(桶加上优先队列)
思路
首先我们要明确的是实现什么
用优先队列做实现的就是两个:出队和进队
进队好办,一个push操作就解决了
但是出队呢,用优先队列似乎有一丢丢难办
那我们要解决的就是出队了
出队
假设队列中元素为{1 3 5 6 7 9}
那么让1出队简单,一个pop的事
那么要让后面的出队呢?
很显然,只有对首元素会影响到答案,首不就是答案吗?
就算队列有成千上万的元素需要出队对当前队列也没有影响
那么我们可以等到当要出队的对象到达队首时再出队
那么我们就需要用一个东西标记他是不是该出队(也就是桶)
桶存放的大小就为它在队列中的数量,显然当数量为0时就该出队了
所以我们在k该进队时就t[k]++;
对应,当k该出队列时就t[k]--;
只要!t[q.top]就q.pop( );
思路就这样
代码
#include<bits/stdc++.h>
#define end putchar('\n')
using namespace std;
inline int read( ){
int sum=0;
bool ft=0;
char ch=getchar( );
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar( );
if(ch=='-')ft=1,ch=getchar( );
while(ch>='0'&&ch<='9'){
sum=sum*10+ch-'0';
ch=getchar( );
}
return ft?-sum:sum;
}
inline void print(int sum){
char a[30];
short w=0;
bool ft=0;
if(sum<0)sum=-sum,ft=1;
while(sum)a[++w]=sum%10+'0',sum/=10;
if(ft)putchar('-');
while(w)putchar(a[w--]);
} //我也不知道为什么要打快读快写
int t[30000100],n,m,tot=1,a[3000000];
priority_queue<int,vector<int>,greater<int> >q;
int main( ){
n=read( ),m=read( );
putchar('0'); //第一个数肯定是0
end;
int k,x=1,r=m;
n=n-1-m;
while(r--){ //入队+输出
a[++tot]=read( );
k=a[tot];
if(!t[k])q.push(k); //小小剪枝,只用一个值代替所有相同值
++t[k]; //队列中t的个数+1
print(q.top( ));
end;
}
while(n--){
a[++tot]=read( );
k=a[tot];
if(!t[k])q.push(k); //小小剪枝,同上
++t[k];
while(x<=tot-m){ //不在区间范围内的出队
--t[a[x]];
++x;
}
while(!t[q.top( )])
q.pop( ); //只要被标记为队列不该有这个数就出队
print(q.top( ));
end;
}
}
或许我讲的不好,但是...
Geass,给我点赞吧