辣鸡 s t d std std 不知道你想表达些啥非要多写个没用的函数还把复杂度上界算错了
这题做法trival,写起来去世
考虑到没有最后一个询问就是常规吉司机线段树,现在我们构造一个 C i = A i − B i C_i=A_i-B_i Ci=Ai−Bi
这样最后就问的是 s u m A − s u m C sum_A-sum_C sumA−sumC
我们发现只用在改 A A A 的时候顺便改一下 C C C 然后把 C C C 中的元素每次修改之后跟 0 c k m a x 0\ ckmax 0 ckmax 一下,这操作不就是 A A A 的操作吗???
于是封装一下就写好了(代码调一年
注意我们要把 C C C 这个集合里的最小值和非最小值分开维护
代码:
#include
#include
#include
#define ri register int
#define fi first
#define se second
#define pb push_back
#define rsz resize
#define sz(x) (int)(x).size()
#define lb lower_bound
#define rb upper_bound
#define all(x) begin(x),end(x)
using namespace std;
using namespace __gnu_pbds;
template<class T>using Tree=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
const int mod=998244353;
typedef long long ll;
inline ll readl(){
ll ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
const int mogic=1e6+7;
struct Hash_table{
vector<int>ori[mogic],vl[mogic];
inline void insert(int x,int Vl){
int t=x<mogic?x:x-x/mogic*mogic;
ori[t].pb(x),vl[t].pb(Vl);
}
inline int query(int x){
for(ri t=x<mogic?x:x-x/mogic*mogic,i=sz(ori[t])-1;~i;--i)if(ori[t][i]==x)return vl[t][i];
return -1;
}
};
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N_=1e6+5;
vector<int>e[N_];
inline void rdt1(int n){for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdt2(int n){for(ri i=2;i<=n;++i)e[read()].pb(i);}
inline void rdg1(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdg2(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v);}
const int N=1e5+5,inf=1e9;
struct Min{
int mn,ct,sn,siz;
ll ss;
inline void clear(){sn=(mn=inf)+1,ss=siz=ct=0;}
inline void Set(int vl){
if(vl==inf)return clear();
sn=inf,ss=mn=vl,ct=siz=1;
}
};
struct Tag{int ad1,ad2;inline void clear(){ad1=ad2=0;}};
struct F{
Min vl;
Tag tg;
inline void clear(){vl.clear(),tg.clear();}
inline void Set(int v){tg.clear(),vl.Set(v);}
};
inline Min operator+(Min a,Tag b){return a.mn+=b.ad1,a.sn+=b.ad2,a.ss+=(ll)a.ct*b.ad1+(ll)(a.siz-a.ct)*b.ad2,a;}
inline void operator+=(Min&a,Tag b){a=a+b;}
inline Tag operator+(Tag a,Tag b){return a.ad1+=b.ad1,a.ad2+=b.ad2,a;}
inline void operator+=(Tag&a,Tag b){a=a+b;}
inline F operator+(F a,Tag b){return b.ad2*=(a.vl.sn<inf),a.vl+=b,a.tg+=b,a;}
inline void operator+=(F&a,Tag b){a=a+b;}
inline void ckmin(int&a,int b){a=a<b?a:b;}
inline Min operator+(Min a,Min b){
if(a.mn>b.mn)swap(a,b);
if(a.mn==b.mn)a.ct+=b.ct,ckmin(a.sn,b.sn);
else ckmin(a.sn,b.mn);
return a.siz+=b.siz,a.ss+=b.ss,a;
}
inline void operator+=(Min&a,Min b){a=a+b;}
inline void operator+=(F&a,F b){if(b.vl.mn!=a.vl.mn+b.tg.ad1)b.tg.ad1=b.tg.ad2;a+=b.tg;}
struct Node{F ori,mn,sn;};
int a[N],n,m;
namespace sgt{
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (l+r>>1)
Node T[N<<2];
inline void pushdown(int p){
T[lc].ori+=T[p].ori;
T[rc].ori+=T[p].ori;
T[lc].mn+=(T[p].ori.vl.mn==T[lc].ori.vl.mn?T[p].mn:T[p].sn);
T[rc].mn+=(T[p].ori.vl.mn==T[rc].ori.vl.mn?T[p].mn:T[p].sn);
T[lc].sn+=T[p].sn;
T[rc].sn+=T[p].sn;
T[p].ori.tg.clear(),T[p].mn.tg.clear(),T[p].sn.tg.clear();
}
inline void pushup(int p){
T[p].ori.vl=T[lc].ori.vl+T[rc].ori.vl;
T[p].sn.vl=T[lc].sn.vl+T[rc].sn.vl;
T[p].mn.vl.clear();
(T[p].ori.vl.mn==T[lc].ori.vl.mn?T[p].mn.vl:T[p].sn.vl)+=T[lc].mn.vl;
(T[p].ori.vl.mn==T[rc].ori.vl.mn?T[p].mn.vl:T[p].sn.vl)+=T[rc].mn.vl;
}
inline void build(int p,int l,int r){
if(l==r)return T[p].ori.Set(a[l]),T[p].mn.Set(0),T[p].sn.Set(inf);
build(lc,l,mid),build(rc,mid+1,r);
pushup(p);
}
inline void update_ori(int p,int l,int r,int v){
if(T[p].ori.vl.mn>=v)return;
if(T[p].ori.vl.sn>v){
Tag tg;
tg.ad1=v-T[p].ori.vl.mn,tg.ad2=0,T[p].ori+=tg,
tg.ad2=tg.ad1,T[p].mn+=tg;
return;
}
pushdown(p);
update_ori(lc,l,mid,v),update_ori(rc,mid+1,r,v);
pushup(p);
}
inline void update_max(int p,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr)return update_ori(p,l,r,v);
pushdown(p);
if(qr<=mid)update_max(lc,l,mid,ql,qr,v);
else if(ql>mid)update_max(rc,mid+1,r,ql,qr,v);
else update_max(lc,l,mid,ql,qr,v),update_max(rc,mid+1,r,ql,qr,v);
pushup(p);
}
inline void update(int p,int l,int r,int v,bool f1,bool f2){
if(f1){
Tag tg;
tg.ad2=v;
if(T[p].mn.vl.mn+v>=0)f1=0,tg.ad1=v,T[p].mn+=tg;
else if(T[p].mn.vl.sn+v>=0)f1=0,tg.ad1=-T[p].mn.vl.mn,T[p].mn+=tg;
}
if(f2){
Tag tg;
tg.ad2=v;
if(T[p].sn.vl.mn+v>=0)f2=0,tg.ad1=v,T[p].sn+=tg;
else if(T[p].sn.vl.sn+v>=0)f2=0,tg.ad1=-T[p].sn.vl.mn,T[p].sn+=tg;
}
if(!(f1|f2))return;
pushdown(p);
update(lc,l,mid,v,T[lc].ori.vl.mn==T[p].ori.vl.mn?f1:f2,f2);
update(rc,mid+1,r,v,T[rc].ori.vl.mn==T[p].ori.vl.mn?f1:f2,f2);
pushup(p);
}
inline void update_add(int p,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
Tag tg;
tg.ad1=tg.ad2=v;
T[p].ori+=tg;
return update(p,l,r,v,1,1);
}
pushdown(p);
if(qr<=mid)update_add(lc,l,mid,ql,qr,v);
else if(ql>mid)update_add(rc,mid+1,r,ql,qr,v);
else update_add(lc,l,mid,ql,qr,v),update_add(rc,mid+1,r,ql,qr,v);
pushup(p);
}
inline ll q1(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return T[p].ori.vl.ss;
pushdown(p);
if(qr<=mid)return q1(lc,l,mid,ql,qr);
if(ql>mid)return q1(rc,mid+1,r,ql,qr);
return q1(lc,l,mid,ql,qr)+q1(rc,mid+1,r,ql,qr);
}
inline ll q2(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return T[p].ori.vl.ss-T[p].mn.vl.ss-T[p].sn.vl.ss;
pushdown(p);
if(qr<=mid)return q2(lc,l,mid,ql,qr);
if(ql>mid)return q2(rc,mid+1,r,ql,qr);
return q2(lc,l,mid,ql,qr)+q2(rc,mid+1,r,ql,qr);
}
#undef lc
#undef rc
#undef mid
}
int main(){
#ifdef ldxcaicai
freopen("lx.in","r",stdin);
#endif
n=read(),m=read();
for(ri i=1;i<=n;++i)a[i]=read();
sgt::build(1,1,n);
for(ri op,l,r;m;--m){
op=read(),l=read(),r=read();
if(op==1)sgt::update_max(1,1,n,l,r,read());
if(op==2)sgt::update_add(1,1,n,l,r,read());
if(op==3)cout<<sgt::q1(1,1,n,l,r)<<'\n';
if(op==4)cout<<sgt::q2(1,1,n,l,r)<<'\n';
}
return 0;
}
一道比较 n a i i v e naiive naiive 的题,发现只需要用 l c t lct lct 维护一坨等比数列的和,但 5 5 5 没有二次剩余于是要写个矩阵或者 a + b 5 a+b\sqrt5 a+b5 来搞一下,代码也挺简单的:
#include
#include
#include
#define ri register int
#define fi first
#define se second
#define pb push_back
#define rsz resize
#define sz(x) (int)(x).size()
#define lb lower_bound
#define rb upper_bound
#define all(x) begin(x),end(x)
using namespace std;
using namespace __gnu_pbds;
template<class T>using Tree=tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
const int mod=998244353;
typedef long long ll;
inline ll readl(){
ll ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
const int mogic=1e6+7;
struct Hash_table{
vector<int>ori[mogic],vl[mogic];
inline void insert(int x,int Vl){
int t=x<mogic?x:x-x/mogic*mogic;
ori[t].pb(x),vl[t].pb(Vl);
}
inline int query(int x){
for(ri t=x<mogic?x:x-x/mogic*mogic,i=sz(ori[t])-1;~i;--i)if(ori[t][i]==x)return vl[t][i];
return -1;
}
};
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N_=1e6+5;
vector<int>e[N_];
inline void rdt1(int n){for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdt2(int n){for(ri i=2;i<=n;++i)e[read()].pb(i);}
inline void rdg1(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v),e[v].pb(u);}
inline void rdg2(int m){for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].pb(v);}
const int N=1e5+5;
int n,m,a[N];
Hash_table S;
struct F{
int x,y;
F(int x=0,int y=0):x(x),y(y){}
inline F conj()const{return F(x,mod-y);}
friend inline F operator+(F a,F b){return F(add(a.x,b.x),add(a.y,b.y));}
friend inline F operator-(F a,F b){return F(dec(a.x,b.x),dec(a.y,b.y));}
friend inline F operator*(F a,F b){return F(add(mul(a.x,b.x),mul(5,mul(a.y,b.y))),add(mul(a.x,b.y),mul(a.y,b.x)));}
friend inline F operator*(F a,int b){return F(mul(a.x,b),mul(a.y,b));}
friend inline F operator/(F a,F b){
int t=dec(mul(b.x,b.x),mul(5,mul(b.y,b.y))),iv=S.query(t);
if(iv==-1){
iv=t?ksm(t,mod-2):1;
S.insert(t,iv);
}
return (a*(b.conj()))*iv;
}
friend inline void operator+=(F&a,F b){a=a+b;}
friend inline void operator-=(F&a,F b){a=a-b;}
friend inline void operator*=(F&a,F b){a=a*b;}
friend inline void operator/=(F&a,F b){a=a/b;}
friend inline F operator^(F a,int p){F ret=F(1,0);for(;p;p>>=1,a*=a)if(p&1)ret*=a;return ret;}
};
const F W0=F(mod+1>>1,mod+1>>1);
struct G{
F pre,suf,ss,vl;
G(F pre=F(0,0),F suf=F(0,0),F ss=F(0,0),F vl=F(0,0)):pre(pre),suf(suf),ss(ss),vl(vl){}
inline void rev(){swap(pre,suf);}
friend inline G operator+(G a,G b){return G(a.pre+a.vl*b.pre,b.suf+b.vl*a.suf,a.ss+b.ss+a.suf*b.pre,a.vl*b.vl);}
};
inline G Set(F v=F(0,0),int k=1){
G t;
F iv=F(1,0)/(F(1,0)-v);
t.vl=v^k;
t.pre=t.suf=(F(1,0)-t.vl)*v*iv;
t.ss=(F(k,0)-t.pre)*iv*v;
return t;
}
namespace lct{
#define lc (son[p][0])
#define rc (son[p][1])
int son[N][2],siz[N],fa[N];
F tg[N],vl[N];
bool rev[N],cov[N];
G T[N];
inline void pushup(int p){
T[p]=Set(vl[p],1),siz[p]=1;
if(lc)T[p]=T[lc]+T[p],siz[p]=siz[lc]+siz[p];
if(rc)T[p]=T[p]+T[rc],siz[p]=siz[p]+siz[rc];
}
inline void pushrev(int p){swap(lc,rc),T[p].rev(),rev[p]^=1;}
inline void pushcov(int p,F v){cov[p]=1,T[p]=Set(tg[p]=vl[p]=v,siz[p]);}
inline void pushdown(int p){
if(rev[p]){
rev[p]^=1;
if(lc)pushrev(lc);
if(rc)pushrev(rc);
}
if(cov[p]){
cov[p]^=1;
if(lc)pushcov(lc,tg[p]);
if(rc)pushcov(rc,tg[p]);
}
}
inline bool which(int x){return x==son[fa[x]][1];}
inline bool isroot(int x){return !fa[x]||(son[fa[x]][0]!=x&&son[fa[x]][1]!=x);}
inline void rotate(int x){
int y=fa[x],z=fa[y],t=which(x);
if(z&&!isroot(y))son[z][which(y)]=x;
fa[x]=z,fa[y]=x,son[y][t]=son[x][t^1],son[x][t^1]=y;
if(son[y][t])fa[son[y][t]]=y;
pushup(y),pushup(x);
}
inline void splay(int x){
static int stk[N],top=0;
stk[top=1]=x;
for(ri i=x;!isroot(i);i=fa[i])stk[++top]=fa[i];
while(top)pushdown(stk[top--]);
while(!isroot(x)){
if(!isroot(fa[x]))rotate(which(x)^which(fa[x])?x:fa[x]);
rotate(x);
}
}
inline void access(int x){for(ri y=0;x;x=fa[y=x])splay(x),son[x][1]=y,(y)&&(fa[y]=x),pushup(x);}
inline void makeroot(int x){access(x),splay(x),pushrev(x);}
inline void link(int x,int y){makeroot(x),splay(y),fa[x]=y;}
inline void cut(int x,int y){makeroot(x),access(y),splay(y),son[y][0]=fa[x]=0,pushup(y);}
inline void update1(int x,int y){
makeroot(1),access(x),splay(x);
fa[son[x][0]]=0,son[x][0]=0,pushup(x),fa[x]=y;
}
inline void update2(int x,int y,int v){
makeroot(x),access(y),splay(y);
pushcov(y,W0^v);
}
inline int query1(int x){return splay(x),add(vl[x].y,vl[x].y);}
inline int query2(int x,int y){return makeroot(x),access(y),splay(y),add(T[y].ss.y,T[y].ss.y);}
inline void init(int p,int k){T[p]=Set(vl[p]=W0^k,siz[p]=1);}
#undef lc
#undef rc
}
int main(){
#ifdef ldxcaicai
freopen("lx.in","r",stdin);
#endif
n=read(),m=read();
for(ri i=1;i<=n;++i)lct::init(i,read());
for(ri i=2;i<=n;++i)lct::fa[i]=read();
for(ri op,x,y;m;--m){
op=read();
if(op==1){
x=read(),y=read();
lct::update1(x,y);
}
if(op==2){
x=read(),y=read();
lct::update2(x,y,read());
}
if(op==3)cout<<lct::query1(read())<<'\n';
if(op==4){
x=read(),y=read();
cout<<lct::query2(x,y)<<'\n';
}
}
return 0;
}
我考试的时候怎么给自己套了个 n \sqrt n n进去呀???(自闭.jpg
而且讲过的原题一坨人没去写???
直接先推一个容斥系数然后枚举整数拆分加个分解质因数再做完全背包就完了。
代码(多套了一个 n \sqrt n n的):
#include
#define ri register int
#define rs register short
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define rsz resize
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
const int mod=1e9+7;
typedef long long ll;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e4+5,M=31;
short top=0,a[N],b[N],pri[N],tot=0,n,m;
int g[M],fac[M],ifac[M],ans=0,cnt[N];
int mt_fac[M][M],mt_ifac[M][M],mt_g[M][M];
bool vis[N];
int ff[N];
inline void calc(){
int coe=1;
for(rs i=1;i<=top;++i){
coe=(1ll*coe*mt_ifac[a[i]][b[i]])%mod*(1ll*ifac[b[i]]*mt_g[a[i]][b[i]]%mod)%mod;
if(!coe)return;
}
for(rs i=1;i<=tot;++i){
ff[0]=1;
for(ri j=1;j<=cnt[i];++j)ff[j]=0;
for(rs j=1;j<=top;++j)for(rs k=1;k<=b[j];++k)
for(ri t=0,up=cnt[i]-a[j];t<=up;++t)Add(ff[t+a[j]],ff[t]);
Mul(coe,ff[cnt[i]]);
if(!coe)return;
}
Add(ans,coe);
}
void dfs(short x,short y){
if(x<y)return;
if(a[top]==x){
++b[top];
calc();
--b[top];
}
else{
a[++top]=x,b[top]=1;
calc();
--top;
}
for(rs i=y,lim=x/2;i<=lim;++i){
if(i==a[top]){
++b[top];
dfs(x-i,i);
--b[top];
}
else{
a[++top]=i,b[top]=1;
dfs(x-i,i);
--top;
}
}
}
inline void Init(int x){for(ri i=n;i>=x;i/=x)cnt[tot]+=i/x;}
inline void init(){
for(rs i=2;i<=n;++i){
if(!vis[i])pri[++tot]=i,Init(i);
for(rs j=1;j<=tot&&(int)i*pri[j]<=n;++j){
vis[i*pri[j]]=1;
if(i==i/pri[j]*pri[j])break;
}
}
fac[0]=ifac[0]=fac[1]=ifac[1]=1;
for(rs i=2;i<=m;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
for(rs i=2;i<=m;++i)Mul(ifac[i],ifac[i-1]);
g[1]=1;
for(rs i=2;i<=m;++i)g[i]=mod-mul(g[i-1],i-1);
for(rs i=1;i<=m;++i)mt_fac[i][0]=mt_ifac[i][0]=mt_g[i][0]=1;
for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_fac[i][j]=mul(mt_fac[i][j-1],fac[i]);
for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_ifac[i][j]=mul(mt_ifac[i][j-1],ifac[i]);
for(rs i=1;i<=m;++i)for(rs j=1;j<=m;++j)mt_g[i][j]=mul(mt_g[i][j-1],g[i]);
}
int main(){
n=read(),m=read();
init();
dfs(m,1);
cout<<ans;
return 0;
}