社区讨论
求卡常,暴力,卡过 #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 条回复,欢迎继续交流。
正在加载回复...