社区讨论

关于用堆卡常

P2827[NOIP 2016 提高组] 蚯蚓参与者 5已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@mk7rmkie
此快照首次捕获于
2026/01/10 11:48
上个月
此快照最后确认于
2026/01/12 19:45
上个月
查看原帖
我通过P5282中的卡常技巧以及查阅的资料终于用16叉堆和AVX512卡过了本题,代码如下。
CPP
#include<bits/extc++.h>
#include<immintrin.h>
#pragma GCC target("avx512f")
using namespace std;
namespace IO
{
    const int SIZE=1<<22;
    char buf[SIZE],*p1=buf,*p2=buf,outbuf[SIZE],*p3=outbuf;
    __attribute__((always_inline)) inline char gc()
    {
        if(p1==p2)
        {
            p2=(p1=buf)+fread(buf,1,SIZE,stdin);
            if(p1==p2) return EOF;
        }
        return *p1++;
    }
    __attribute__((always_inline)) inline int read()
    {
        int res=0;
        char c=gc();
        while(c<'0' || c>'9') c=gc();
        while(c>='0' && c<='9' && c!=EOF) res=(res<<1)+(res<<3)+(c^48),c=gc();
        return res;
    }
    __attribute__((always_inline)) inline void pc(char c)
    {
        if(p3-outbuf==SIZE)
        {
            fwrite(outbuf,1,SIZE,stdout);
            p3=outbuf;
        }
        *p3++=c;
    }
    __attribute__((always_inline)) inline void write(int x)
    {
        if(x==0) return pc('0'),void();
        int num[50],cnt=0;
        while(x) num[++cnt]=x%10,x/=10;
        for(int i=cnt;i>=1;i--) pc(num[i]+'0');
    }
    __attribute__((always_inline)) inline void flush() 
    {
        fwrite(outbuf,1,p3-outbuf,stdout);
        p3=outbuf;
    }
}
using namespace IO;
int a[7110010]__attribute__((aligned(64)));
int cnt;
__attribute__((always_inline)) inline void push(int x)
{
    int cur=++cnt;
    while(__builtin_expect(cur>1,1))
    {
        int p=((cur-2)>>4)+1;
        if(a[p]>=x) break;
        a[cur]=a[p];
        cur=p;
    }
    a[cur]=x;
}
__attribute__((always_inline)) inline void down(int u)
{
    int x=a[u],c;
    while(1)
    {
        c=((u-1)<<4)+2;
        if(c>cnt) break;
        int maxidx=c;
        if(__builtin_expect(c+15<=cnt,1))
        {
            __m512i v=_mm512_loadu_si512((__m512i*)&a[c]);
            int mv=_mm512_reduce_max_epi32(v);
            unsigned int mask=_mm512_cmpeq_epi32_mask(v,_mm512_set1_epi32(mv));
            maxidx=c+__builtin_ctz(mask);
        }
        else for(int i=c+1;i<=cnt;i++) if(a[i]>a[maxidx]) maxidx=i;
        if (x>=a[maxidx]) break;
        a[u]=a[maxidx];
        u=maxidx;
    }
    a[u]=x;
}
__attribute__((always_inline)) inline void pop()
{
    a[1]=a[cnt--];
    down(1);
}
int n,m,q,u,v,t,all;
int main()
{
    n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
    for(int i=1;i<=n;i++) a[i]=read();
    cnt=n;
    for(int i=(cnt-2)/16+1;i>=1;i--) down(i);
    int next=t;
    long double p=(long double)u/v;
    for(int i=1;i<=m;i++)
    {
        int top=a[1]+all;
        int q1=int(top*p),q2=top-q1;
        all+=q;
        a[1]=q1-all;
        down(1);
        push(q2-all);
        if(__builtin_expect(i==next,0)) write(top),pc(' '),next+=t;
    }
    pc('\n');
    next=t;
    for(int i=1;cnt;i++,pop()) if(__builtin_expect(i==next,0)) write(a[1]+all),pc(' '),next+=t;
    flush();

    return 0;
}
话说有没有能不用指令集通过的写法,毕竟CCF不给用。

回复

8 条回复,欢迎继续交流。

正在加载回复...