SJTU OJ 1558 最长序列问题
这道题我是基本照搬ciociooo的博客的做法,只是其中的优先级队列我改用了自己写的版本。同时又添加了一些注释方便我看懂。
下面是代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int mmax(int x, int y){
return x>y ? x:y;
}
struct mypair{
int first;
int second;
mypair(){}
mypair(int f, int s):first(f), second(s){}
bool operator>(const mypair & other)const{
return first > other.first;
}
};
template<class T>
class priorityQueue
{
private:
int currentsize;
T * array;
int maxsize;
void doublespace();
void buildheap();
void percolatedown(int hole);
public:
priorityQueue(int cap = 200010)
{
array = new T[cap];
maxsize = cap;
currentsize = 0;
}
~priorityQueue(){delete []array;}
bool isEmpty() const{return currentsize == 0;}
void push(const T &x);
bool empty();
T pop();
T top() const{return array[1];}
};
template<class T>
void priorityQueue<T>::push(const T& x)
{
if (currentsize == maxsize-1) doublespace();
int hole = ++ currentsize;
for (;hole>1 && x > array[hole/2]; hole/=2)
array[hole] = array[hole/2];
array[hole] = x;
}
template<class T>
T priorityQueue<T>::pop()
{
T maxitem;
maxitem = array[1];
array[1] = array[currentsize--];
percolatedown(1);
return maxitem;
}
template<class T>
void priorityQueue<T>::percolatedown(int hole)
{
int child;
T tmp = array[hole];
for (; hole*2 <= currentsize; hole = child)
{
child = hole * 2;
if (child != currentsize && array[child+1] > array[child])
child++;
if (array[child] > tmp) array[hole] = array[child];
else break;
}
array[hole] = tmp;
}
template<class T>
void priorityQueue<T>::doublespace()
{
T * tmp = array;
maxsize *= 2;
array = new T[maxsize];
for (int i=1; i<=currentsize; i++)
{
array[i] = tmp[i];
}
delete[] tmp;
}
template<class T>
bool priorityQueue<T>::empty(){
return currentsize == 0;
}
struct node{
int v;//标签号;
int bh;//原本在第几位;
bool operator<(const node &other)const{
return v < other.v;
}
};
node P[100005];
int N,K;
int v[100005],cnt[100005] = {0};
void _init()
{
scanf("%d%d", &N, &K);
for(int i=1;i<=N;i++){
scanf("%d", &(P[i].v));
P[i].bh = i;
}
sort(P+1,P+N+1);//相同标签的放在一起了;
int bh=0;
P[0].v=-1;v[0]=-1;
for(int i=1;i<=N;i++)
{
if(P[i].v != P[i-1].v) bh++;
v[P[i].bh]=bh;//根据标签顺序重新从123开始标记标签;
}
}
priorityQueue<mypair> my_q;
void _solve()
{
while(!my_q.empty()) my_q.pop();
int now,ans;
now=ans=cnt[v[1]]=1;
my_q.push(mypair(cnt[v[1]],v[1]));//first是v[i]标签号出现的次数;
for(int i=1,j=1;i<=N&&j<=N;)
{
while(j<N&&now<K+1)//右端点延伸;
{
j++;
if(!cnt[v[j]]) now++;
cnt[v[j]]++;
my_q.push(mypair(cnt[v[j]],v[j]));
}
while(now==K+1&&j<N&&cnt[v[j+1]]!=0)//右侧还有已有标签,继续延伸;
{
j++;
cnt[v[j]]++;
my_q.push(mypair(cnt[v[j]],v[j]));
}
while((!my_q.empty())&&(my_q.top().first!=cnt[my_q.top().second])){
my_q.pop();//去掉已经无效的;
}
if(!my_q.empty()){
ans = mmax(ans,my_q.top().first);
}
cnt[v[i]]--;//左端点右移一位;
if(cnt[v[i]]==0) now--;
my_q.push(mypair(cnt[v[i]],v[i]));
i++;
}
printf("%d", ans);
}
int main()
{
_init();
_solve();
return 0;
}
这个做法很巧妙,原创者的代码也写得很优雅。