SJTU OJ 1558 最长序列问题

SJTU OJ 1558 最长序列问题

原题链接

这道题我是基本照搬ciociooo的博客的做法,只是其中的优先级队列我改用了自己写的版本。同时又添加了一些注释方便我看懂。
下面是代码:

#include 
#include 
#include 
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::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::pop()
{
    T maxitem;
    maxitem = array[1];
    array[1] = array[currentsize--];
    percolatedown(1);
    return maxitem;
}
template<class T>
void priorityQueue::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::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::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 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(j1)//右端点延伸;
        {
            j++;
            if(!cnt[v[j]]) now++;
            cnt[v[j]]++;
            my_q.push(mypair(cnt[v[j]],v[j]));
        }
        while(now==K+1&&j1]]!=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;
}

这个做法很巧妙,原创者的代码也写得很优雅。

你可能感兴趣的:(SJTUOJ)