社区讨论

求卡常,暴力,卡过 #4 就行

P14638[NOIP2025] 序列询问参与者 1已保存回复 0

讨论操作

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

当前回复
0 条
当前快照
1 份
快照标识符
@mj7woqw7
此快照首次捕获于
2025/12/16 09:30
2 个月前
此快照最后确认于
2025/12/16 19:08
2 个月前
查看原帖
CPP
#include<bits/stdc++.h>
char buf[1<<18+1],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define putchar putchar_unlocked
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define push_back emplace_back
//#define int long long
using namespace std;
constexpr int N=5e4+1,B=__lg(N)+1,Q=1025;
inline void read(int&x){
    int f=1;
    char ch=getchar();
    x=0;
    while(!isdigit(ch)){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x*=f;
    return;
}
inline void read(long long&x){
    int f=1;
    char ch=getchar();
    x=0;
    while(!isdigit(ch)){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x*=f;
    return;
}
inline void write(unsigned long long x){
    if(x>=10)
        write(x/10);
    putchar((x%10)^48);
    return;
}
inline void writeln(unsigned long long x){
    write(x);
    putchar('\n');
    return;
}
int n,isA=1,q,a[N],lgg[N];
long long sum[N],ans[Q];
//int n,isA=1,q,a[N],sum[N],ans[Q],lgg[N];
struct STT{
    int n,len;
    vector<long long>st[B];
    STT(){}
    STT(const vector<long long>&vec){
        st[0]=vec;
//        swap(st[0],vec);
        n=vec.size()-1,len=lgg[n];
        for(int i=1/*,t=1*/;i<=len;i++/*,t<<=1*/){
            st[i]=st[i-1];
            for(int j=1;j+(1<<(i-1))<=n;j++)
                st[i][j]=max(st[i][j],st[i-1][j+(1<<(i-1))]);
        }
    }
    __inline long long query(int l,int r){
        int leng=lgg[r-l+1];
        return max(st[leng][l],st[leng][r-(1<<leng)+1]);
    }
};/*
struct STtable{
    int n,len;
    int st[B][10001];
    STtable(){}
    STtable(vector<int>vec){
        n=vec.size()-1,len=__lg(n)+1;
        for(int i=1;i<=n;i++)
            st[0][i]=vec[i];
        for(int i=1;i<=len;i++){
            for(int j=1;j<=n;j++){
                st[i][j]=st[i-1][j];
                if(j+(1<<(i-1))<=n)
                    st[i][j]=max(st[i][j],st[i-1][j+(1<<(i-1))]);
            }
        }
    }
    int query(int l,int r){
        int leng=__lg(r-l+1);
        return max(st[leng][l],st[leng][r-(1<<leng)+1]);
    }
};*/
#define STtable STT
struct RMQqueue{
    deque<pair<long long,long long> >q;
    vector<long long>vec;
    long long cur;
    RMQqueue(){}
    RMQqueue(const vector<long long>&x){
        vec=x;
        while(!q.empty())
            q.pop_back();
        cur=0;
    }
    long long query(long long l,long long r){
        while(cur<r){
            while(!q.empty()&&q.back().second<=vec[cur+1])
                q.pop_back();
            q.push_back(cur+1,vec[cur+1]);
            cur++;
        }
        while(!q.empty()&&q.front().first<l)
            q.pop_front();
        return q.front().second;
    }
};
vector<pair<int,int> >queries;
vector<long long>best[N];//best[element][len]=val
STtable rmqbest;
STT rbest;
#define qsum(l,r) (sum[(r)]-sum[(l)-1])
/*
__inline int qsum(int l,int r){
    return sum[r]-sum[l-1];
}*/
struct RMQueue{
    deque<pair<int,long long> >q;
    int cur,lll,llll;
    #define qry(x) qsum((x),(x)+lll-1)
    /*
    int qry(int x){
        return qsum(x,x+lll-1);
    }*/
    RMQueue(){}
    RMQueue(int lll):lll(lll){
        q.clear();
        cur=0;
        llll=n-lll+1;
    }
    long long query(int l,int r){
        if(__builtin_expect(cur!=llll,1)){
            while(!q.empty()&&q.back().second<=qry(cur+1))
                q.pop_back();
            q.push_back(cur+1,qry(cur+1));
            cur++;
        }
        if(__builtin_expect(q.front().first<l,1))
            q.pop_front();
        return q.front().second;/*
        if(cur<n){
            while(!q.empty()&&q.back().second<qry(cur+1))
                q.pop_back();
            q.push_back({cur+1,qry(cur+1)});
        }
        cur++;
        if((cur>=lll&&!q.empty())&&q.front().first<cur-lll+1)
            q.pop_front();
        return q.front().second;*/
    }
};
__inline unsigned long long get_ans(const vector<long long>&anss){
    unsigned long long ret=0;
    for(long long i=1;i<=n;i++)
        ret^=((unsigned long long)(i*anss[i]));
    return ret;
}/*
string get_ans(const vector<int>&ans){
    stringstream ss;
    for(int i=1;i<=n;i++)
        ss<<ans[i]<<" \n"[i==n];
    return ss.str();
}*/
vector<long long>calc(long long len){
    vector<long long>val(1,0),ret(1,0);
    for(long long i=1;i<=n-len+1;i++)
        val.push_back(qsum(i,i+len-1));
    RMQqueue rmq(val);
    for(long long i=1;i<=n;i++)
        ret.push_back(rmq.query(max(1ll,i-len+1),min(i,n-len+1)));
    return ret;
}
void calc_best(){
    vector<long long>ret;
//    deque<pair<int,int> >q[N];
    vector<RMQueue>rmq(1);
    for(int i=1;i<=n;i++)
        rmq.push_back(RMQueue(i));
    for(int i=1;i<=n;i++){
        ret.resize(1);
        for(int j=1;j<=n;j++)
            ret.push_back(rmq[j].query(i-j+1,i));
//        if(i==1)
        rmqbest=STtable(ret);
        for(int j=1;j<=q;j++){
            auto[l,r]=queries[j-1];
            ans[j]^=(unsigned long long)(i*rmqbest.query(l,r));
        }
    }
    return;
}
signed main(){
    lgg[1]=0;
    for(int i=2;i<=10000;i++)
        lgg[i]=lgg[i>>1]+1;
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    read(q);
    for(int i=1,l,r;i<=q;i++){
        read(l),read(r);
        queries.push_back(l,r);
        if(l!=r)
            isA=0;
    }
    if(isA){
        for(auto[l,r]:queries)
            writeln(get_ans(calc(l)));
        return 0;
    }
    if(n<=10000&&q<=128){
        calc_best();
        for(int i=1;i<=q;i++){
            write(ans[i]);
            putchar('\n');
        }
        return 0;
    }
    for(int i=1;i<=n;i++)
        best[i].resize(min(n,((n>30000||q>512)?32ll:n))+1);
    for(int i=1;i<=min(n,((n>30000||q>512)?32ll:n));i++){
        auto tmp=calc(i);
        for(int j=1;j<=n;j++)
            best[j][i]=tmp[j];
    }
    for(int i=1;i<=n;i++){
        rbest=STT(best[i]);
        for(int j=1;j<=q;j++){
            auto[l,r]=queries[j-1];
            ans[j]^=((unsigned long long)(i*rbest.query(l,r)));
        }
    }
    for(int i=1;i<=q;i++)
        writeln(ans[i]);
    return 0;
}
除了 calc_best 函数基本没有花时间。
calc_best 函数中可以通过调小范围来在洛谷测时间。
calc_best 的两个瓶颈分别是建 ST 表和单调队列查询,可以对这两个卡。
建议需要经过实测,可以悬赏 4 个小号的关注。

回复

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

正在加载回复...