题解 P8527【[Ynoi2003] 樋口円香】
题意
给出长为 的序列 , 序列初始为 , 次操作,每次给出 中的一个区间 与 ,执行 。
求出所有操作后的 序列。
,。
思路
乐子一血。
对序列 按照块长为 分块,对于一次操作,若 同块,则直接加,否则先对散块暴力,整块存下来暂不处理。
所有询问的散块处理完之后,处理整块。对于每个块 ,我们记录 表示这个块加到 序列中以 开始的等长区间的次数,。令这个块对 的贡献为 ,则有 ,可以卷积。
复杂度为 ,取 得到最优复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=131072,mod=998244353;
namespace Init{
int fac[N],ifac[N],inv[N],G[17][N];
inline int qpow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
inline void getG(){
for(int i=0;i<17;i++){
int *P=G[i],W=1<<i;
P[0]=1;
P[1]=qpow(3,(mod-1)/(1<<i+1));
const int tmp=P[1];
for(int j=2;j<W;j++)
P[j]=1ll*P[j-1]*tmp%mod;
}
}
inline void Prefix(int L){
fac[0]=1;
for(int i=1;i<=L;i++)
fac[i]=1ll*fac[i-1]*i%mod;
ifac[L]=qpow(fac[L],mod-2);
for(int i=L;i>=1;i--)
ifac[i-1]=1ll*ifac[i]*i%mod;
for(int i=1;i<=L;i++)
inv[i]=1ll*fac[i]*ifac[i-1]%mod;
}
}
using namespace Init;
namespace Poly{
int lim,rev[N];
int F[N],G[N],H[N];
inline void init(int n,int mode=1){
if(mode){
int l=0;
for(lim=1;lim<=n;lim<<=1)l++;
for(int i=1;i<lim;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}else{
for(lim=1;lim<=n;lim<<=1);
}
}
inline void NTT(int *a,int T){
for(int i=0;i<lim;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int i=1,o=0;i<lim;i<<=1,o++){
const int *P=::G[o];
for(int j=0;j<lim;j+=(i<<1)){
int t1,t2;
for(int k=0;k<i;k++){
t1=a[j+k];
t2=1ll*P[k]*a[i+j+k]%mod;
a[j+k]=(t1+t2)%mod;
a[i+j+k]=(t1-t2+mod)%mod;
}
}
}
if(T==1) return ;
int Inv=qpow(lim,mod-2);
reverse(a+1,a+lim);
for(int i=0;i<lim;i++)
a[i]=1ll*a[i]*Inv%mod;
}
inline void Mul(int *a,int *b){
for(int i=0;i<lim;i++)
F[i]=b[i];
NTT(a,1),NTT(F,1);
for(int i=0;i<lim;i++)
a[i]=1ll*a[i]*F[i]%mod;
NTT(a,-1);
}
}
const int T=1e5+10,Q=1e6+10,sq=sqrt(1.0*T*T*log2(T)/Q+Q)*2;
int n,q,blk,a[T],b[T],c[N],d[N],bel[T],bl[T],br[T];
struct Query{
int l,bL,bR,L;
}que[Q];
inline void solve(int bL,int bR){
int D=bel[bL],len=bR-bL+1;
for(int i=0;i<=Poly::lim;i++)
c[i]=d[i]=0;
for(int i=1;i<=q;i++)
if(que[i].bL<=D&&D<=que[i].bR)
c[que[i].L+bL-que[i].l]++;
for(int i=1;i<=len;i++)
d[i-1]=a[bL+i-1];
Poly::Mul(c,d);
for(int i=1;i<=n;i++)
b[i]+=c[i];
}
int main(){
n=read();
getG(),Poly::init(n+2000);
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i+=sq){
blk++;
bl[blk]=i,br[blk]=min(i+sq-1,n);
for(int j=bl[blk];j<=br[blk];j++)
bel[j]=blk;
}
q=read();
for(int i=1;i<=q;i++){
int l=read(),r=read(),L=read();
int bL=bel[l],bR=bel[r];
if(bL==bR){
for(int j=l;j<=r;j++)
b[L+j-l]+=a[j];
}else{
for(int j=l;j<=br[bL];j++)
b[L+j-l]+=a[j];
for(int j=bl[bR];j<=r;j++)
b[L+j-l]+=a[j];
que[i]={l,bL+1,bR-1,L};
}
}
for(int i=1;i<=blk;i++)
solve(bl[i],br[i]);
for(int i=1;i<=n;i++)
write(b[i]),putc('\n');
flush();
}
再见 qwq~
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通