BZOJ4524: [Cqoi2016]伪光滑数

可持久化可并堆QWQ
传送门:
http://blog.csdn.net/liuguangzhe1999/article/details/51132255
听说这位大神AK了省选%%%
主要思想就是讲一个可并堆当做一个状态然后转递给后面的状态

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdlib>
using namespace std;
#define ll long long
char c;
inline int ra(){return rand();}
inline void read(int &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
inline void read(ll &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
struct Sp{int u,v;ll key;inline friend bool operator <(Sp a,Sp b){return a.key<b.key;}};
priority_queue<Sp>Q;
struct Node
{
    Node *lc,*rc;
    ll D,flag;
    Node(){D=1,flag=1,lc=NULL,rc=NULL;};
}*Cache;
int Cachetot=10000001;
const
 int MaxCache=1000000;
ll con;
inline Node *New(){
con++;if(Cachetot>MaxCache)Cache=new Node[MaxCache],Cachetot=0;Cache[Cachetot].flag=1;return Cache+Cachetot++;}
ll n;
int t,m;
inline void Pushdown(Node *&A)
{
    t++;
    Node *AA;
    if(A->lc)
    {
    AA=A->lc;
    A->lc=New();*A->lc=*AA;
    A->lc->flag*=A->flag;
    A->lc->D*=A->flag;
    }
    if(A->rc)
    {
    AA=A->rc;
    A->rc=New();*A->rc=*AA;
    A->rc->flag*=A->flag;
    A->rc->D*=A->flag;
    }
    A->flag=1;
}
inline Node*Addflag(Node *A,ll flag)
{
    Node *N=New();
    *N=*A;
    N->flag*=flag;
    N->D*=flag;
    return N;
}
inline ll Top(Node *L)
{return L==NULL?0:L->D;}
Node*Merge(Node *L,Node *R)
{
    Node *A=New();
    if(L==NULL)return *A=*R,A;
    if(R==NULL)return *A=*L,A;
    if(L->flag!=1)Pushdown(L);
    if(R->flag!=1)Pushdown(R);
    if(ra()&1)
      {
        if(L->D<R->D)*A=*R,A->lc=Merge(R->lc,L),A->rc=R->rc;
        else  *A=*L,A->lc=Merge(L->lc,R),A->rc=L->rc;
      }
    else
      {
        if(L->D<R->D)*A=*R,A->rc=Merge(R->rc,L),A->lc=R->lc;
        else  *A=*L,A->rc=Merge(L->rc,R),A->lc=L->lc;
      }
     return A;
}

inline ll Pop(Node *&A)
{
    if(A==NULL)return 0;
    int res;
    if(A->flag!=1)Pushdown(A);
    if(A->lc==NULL)return res=A->D,A=A->rc,res; 
    if(A->rc==NULL)return res=A->D,A=A->lc,res; 
    return res=A->D,A=Merge(A->lc,A->rc),res;
}
bool Check[2346];
int tot,Prime[2346];
Node *f[236][2346];
Node *g[236][2346];
ll V[236][23996];

inline void Pre()
{
    int i,j,t;
    ll k;
    read(n),read(m);
    for(i=2;i<128;i++)
    {
        if(!Check[i])
            {
                Prime[++tot]=i;
                ll last=1;
                for(j=1,k=i;k>=last&&k<=n;j++,last=k,k*=i)V[tot][j]=k;
            }
        for(j=1;j<=tot&&(k=i*Prime[j])<128;j++)
        {
            Check[k]=true;
            if(i%Prime[j]==0)break;
        }
    }
    g[0][0]=New();
     for(i=1;i<=tot;i++)
       g[i][0]=g[0][0];
    for(i=1;i<=tot;i++)
     for(j=1;V[i][j];j++)
     {
        if(i==17&&j==10)
        i++,i--;
        for(k=1;k<=j;k++)
            if(g[i-1][j-k])f[i][j]=Merge(f[i][j],Addflag(g[i-1][j-k],V[i][k]));
      Q.push((Sp){i,j,f[i][j]->D});
      g[i][j]=Merge(g[i-1][j],f[i][j]);
    }
}
Sp Kyy[100001];
int ttt;
inline void Ans()
{
    Sp K;
    for(int i=1;i<m;i++)
    {
        K=Q.top();
        Q.pop();
        Pop(f[K.u][K.v]);
        Q.push((Sp){K.u,K.v,Top(f[K.u][K.v])});
    }
    K=Q.top();
    cout<<K.key<<endl;
}

int main()
{
    Pre();
    Ans();
    return 0;
}

你可能感兴趣的:(BZOJ4524: [Cqoi2016]伪光滑数)