$POJ2442 Sequence$ 堆

正解:堆

解题报告:

传送门$QwQ$

全场除了我都切了系列$kk$

首先看$n=2$的情况.

首先暴力不说?就记录一个$sum$再分别记录$xy$两维的下标存到堆里面每次取队头并继续扩展就完事$QwQ$.

然后发现会枚举重复,就不太优秀,考虑优化$QwQ$.

于是考虑记录下这个点是扩展$x$的时候扩展来的还是扩展$y$的时候扩展来的,如果是扩展$x$的时候扩展来的就只扩展$x$了,否则就$xy$都要扩展.

这样就能保证每个状态只会被扩展一次了.

然后现在考虑$n>2$的情况.

就直接当$n=2$地做$n-1$次就完事

然后这个复杂度是$O(nmlogm)$的.

优化康考试总结$QwQ$,$over$

 

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<vector>
#include<cstdio>
#include<queue>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)

const int N=1e5+10;
int n,m,as;
vector<int>V[N],v;
struct node{int sum,fr,nwx,nwy;};
priority_queue<node>Q;

il int read()
{
    ri x=0;rb y=1;rc ch=gc;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')y=0,ch=gc;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il bool cmp(ri gd,ri gs){return gd>gs;}
il bool operator < (node gd,node gs){return gd.sum>gs.sum;}
il void work(ri x,ri y)
{
    ri szx=V[x].size(),szy=V[y].size();
    while(Q.size())Q.pop();;v.clear();Q.push((node){V[x][0]+V[y][0],0,0,0});
    rp(i,1,m)
    {
        node nw=Q.top();Q.pop();v.push_back(nw.sum);
        if(nw.nwx+1<szx)Q.push((node){nw.sum-V[x][nw.nwx]+V[x][nw.nwx+1],1,nw.nwx+1,nw.nwy});
        if(nw.fr)continue;
        if(nw.nwy+1<szy)Q.push((node){nw.sum-V[y][nw.nwy]+V[y][nw.nwy+1],0,nw.nwx,nw.nwy+1});
    }
    V[y]=v;
}

int main()
{
    //freopen("2442.in","r",stdin);//freopen("2442.out","w",stdout);
    ri T=read();
    while(T--)
    {
        n=read();m=read();as=0;
        rp(i,1,n){V[i].clear();rp(j,1,m)V[i].push_back(read());sort(V[i].begin(),V[i].end());}
        rp(i,2,n)work(i-1,i);rp(i,0,m-1)printf("%d ",V[n][i]);printf("
");
    }
    return 0;
}
View Code

 

原文地址:https://www.cnblogs.com/lqsukida/p/gql_boom0QAQ.html