T1:
处理出左右比他大的范围
然后分有没有覆盖分别维护一下即可
注意
z
k
w
zkw
zkw由于区间
[
l
−
1
,
r
+
1
]
[l-1,r+1]
[l−1,r+1]所以处理到
M
≤
n
+
1
M\le n+1
M≤n+1
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
char obuf[RLEN],*ib=obuf,*ob=obuf+RLEN;
inline void pc(char x){
(ib==ob)&&(fwrite(obuf,1,RLEN,stdout),ib=obuf);
*ib++=x;
}
inline void write(int x){
static int top=0;
static char stk[20];
while(x)stk[++top]=x%10,x/=10;
while(top)pc(stk[top--]+'0');
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
cs int N=1000005;
char xxx;
struct Seg{
int mx[(1<<21)|5],M;
#define lc (u<<1)
#define rc ((u<<1)|1)
void init(int n){
for(M=1;M<=n+1;M<<=1);
}
inline void update(int u,int k){
u+=M;chemx(mx[u],k);
for(u>>=1;u;u>>=1)mx[u]=max(mx[lc],mx[rc]);
}
inline int query(int l,int r){
int res=0;
for(l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
if(!(l&1))chemx(res,mx[l^1]);
if(r&1)chemx(res,mx[r^1]);
}return res;
}
#undef lc
#undef rc
}t1,t2,t3;
int n,m,a[N],L[N],R[N],len[N],stk[N],buc[N],top,id[N],ps[N],ans[N];
struct qry{
int l,r,w,id;
}q[N];
int adj1[N],nxt1[N],adj2[N],nxt2[N],tot;
pii to1[N],to2[N];
char yyy;
int main(){
n=read();t1.init(n),t2.init(n),t3.init(n);
for(int i=1;i<=n;i++)a[i]=read(),id[i]=i;
for(int i=1;i<=n;i++){
while(top&&a[stk[top]]>=a[i])top--;
L[i]=stk[top]+1,stk[++top]=i;
}
top=0;stk[0]=n+1;
for(int i=n;i>=1;i--){
while(top&&a[stk[top]]>=a[i])top--;
R[i]=stk[top]-1,stk[++top]=i;
}
for(int i=1;i<=n;i++)len[i]=R[i]-L[i]+1,buc[len[i]]++;
for(int i=n;i;i--)buc[i]+=buc[i+1];
for(int i=1;i<=n;i++)id[buc[len[i]]--]=i;
for(int i=1;i<=n;i++)buc[i]=0;
m=read();
for(int i=1;i<=m;i++){
int l=read(),r=read(),w=read();
q[i]=(qry){l,r,w,i};
buc[w]++;
nxt1[++tot]=adj1[l],adj1[l]=tot;
}
for(int i=n;i;i--)buc[i]+=buc[i+1];
for(int i=m;i;i--)ps[buc[q[i].w]--]=i;
for(int i=1,j=1,l,r,w;i<=m;i++){
l=q[ps[i]].l,r=q[ps[i]].r,w=q[ps[i]].w;
while(j<=n&&len[id[j]]>=w){
t1.update(L[id[j]],a[id[j]]);
t2.update(R[id[j]],a[id[j]]);
j++;
}
ans[q[ps[i]].id]=max(t1.query(l,r-w+1),t2.query(l+w-1,r));
}
for(int i=1;i<=n;i++)nxt2[i]=adj2[L[i]],adj2[L[i]]=i;
for(int i=1;i<=n;i++){
for(int e=adj2[i];e;e=nxt2[e]){
t3.update(R[e],a[e]);
}
for(int e=adj1[i];e;e=nxt1[e]){
chemx(ans[q[e].id],t3.query(q[e].r,n));
}
}
for(int i=1;i<=m;i++)write(ans[i]),pc('\n');
fwrite(obuf,1,ib-obuf,stdout);
return 0;
}
T2:
显然的
l
c
t
lct
lct维护一下链即可
然后再写颗
s
p
l
a
y
splay
splay维护虚儿子
这样据说由奇妙的分析是一个
l
o
g
log
log的
注意存储虚儿子的标号
s
p
l
a
y
splay
splay只能记儿子而不是下条链的根
似乎把
s
i
z
,
v
a
l
siz,val
siz,val记成二元组会方便很多
实现细节参考代码
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+b>=mod)?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b-mod);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
cs int N=100006,bas=257933,ib=Inv(bas);
int pw[N],ipw[N],n,fg;
inline void init_pw(){
pw[0]=ipw[0]=1;
for(int i=1;i<N;i++)pw[i]=mul(pw[i-1],bas),ipw[i]=mul(ipw[i-1],ib);
}
namespace sply{
cs int N=::N<<1;
int fa[N],son[N][2],s[N],vl[N],sz[N],wt[N];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline void init(int u,int k,int t){
s[u]=vl[u]=k,sz[u]=wt[u]=t;
s[u+n]=vl[u+n]=0,sz[u+n]=wt[u+n]=0;
}
inline void init_node(int u,int k,int t){
s[u]=vl[u]=k,sz[u]=wt[u]=t;
lc(u)=rc(u)=fa[u]=0;
}
inline bool isrc(int u){
return rc(fa[u])==u;
}
inline void pushup(int u){
s[u]=vl[u],sz[u]=wt[u];
if(rc(u))s[u]=add(s[rc(u)],mul(s[u],pw[sz[rc(u)]])),sz[u]+=sz[rc(u)];
if(lc(u))s[u]=add(s[u],mul(s[lc(u)],pw[sz[u]])),sz[u]+=sz[lc(u)];
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=isrc(v);
if(z)son[z][isrc(u)]=v;
fa[v]=z;
son[u][t]=son[v][t^1];
fa[son[v][t^1]]=u;
son[v][t^1]=u,fa[u]=v;
pushup(u),pushup(v);
}
inline void splay(int u,int goal=0){
while(fa[u]!=goal){
if(fa[fa[u]]!=goal)
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
}
inline int insert(int r,int u,int k,int t){
r=r+n,init_node(u,k,t);
int p=r;
while(rc(p))p=rc(p);
rc(p)=u,fa[u]=p,pushup(p);
splay(p),splay(r);
return s[r];
}
inline int delet(int r,int u){
r=r+n;
splay(u);
int p=lc(u);
while(rc(p))p=rc(p);
splay(p,u);
rc(p)=rc(u);fa[rc(u)]=p,fa[p]=0,lc(u)=rc(u)=fa[u]=0;
pushup(p);splay(r);
return s[r];
}
#undef lc
#undef rc
}
namespace lct{
int fa[N],son[N][2],s[N],sz[N],xs[N],xsz[N];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline void init(int u){
s[u]=u,sz[u]=1;sply::init(u,u,1);
}
inline bool isrt(int u){
return (!fa[u])||(lc(fa[u])!=u&&rc(fa[u])!=u);
}
inline bool isrc(int u){
return rc(fa[u])==u;
}
inline void pushup(int u){
s[u]=add(xs[u],mul(u,pw[xsz[u]]));sz[u]=xsz[u]+1;
if(rc(u))s[u]=add(s[rc(u)],mul(s[u],pw[sz[rc(u)]])),sz[u]+=sz[rc(u)];
if(lc(u))s[u]=add(s[u],mul(s[lc(u)],pw[sz[u]])),sz[u]+=sz[lc(u)];
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=isrc(v);
if(!isrt(u))son[z][isrc(u)]=v;
fa[v]=z;
son[u][t]=son[v][t^1];
fa[son[v][t^1]]=u;
son[v][t^1]=u,fa[u]=v;
pushup(u),pushup(v);
}
inline void splay(int u,int goal=0){
while(!isrt(u)&&fa[u]!=goal){
if(!isrt(fa[u])&&fa[fa[u]]!=goal)
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
}
inline int nxt(int u){
u=rc(u);
while(lc(u))u=lc(u);
return u;
}
inline int firs(int u){
while(lc(u))u=lc(u);return u;
}
inline void access(int u){
for(int v=0,pr=0;u;v=u,u=fa[u]){
splay(u);
if(rc(u)){
int p=nxt(u);splay(p,u);
xsz[u]+=sz[rc(u)],xs[u]=sply::insert(u,rc(u),s[rc(u)],sz[rc(u)]);
}
if(v)xsz[u]-=sz[v],xs[u]=sply::delet(u,pr);
rc(u)=v,pushup(u);pr=firs(u),splay(pr,u);
}
}
inline void link(int u,int f){
init(u);
fa[u]=f;
access(f),splay(f);
xsz[f]+=1;
xs[f]=sply::insert(f,u,s[u],sz[u]);
access(u);splay(1);
}
inline int query(int k){
splay(1);
return s[1];
}
#undef lc
#undef rc
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
freopen("my.out","w",stdout);
#endif
n=read();init_pw();
lct::init(1);
for(int i=2;i<=n;i++){
int f=read();
lct::link(i,f);
cout<<lct::query(i)<<'\n';
}return 0;
}
T3:
考虑颜色不同的环的方案数
是
f
n
=
f
n
−
1
∗
(
c
−
2
)
+
f
n
−
2
∗
(
c
−
1
)
f_n=f_{n-1}*(c-2)+f_{n-2}*(c-1)
fn=fn−1∗(c−2)+fn−2∗(c−1)
但是注意对于
n
>
3
n>3
n>3才满足这个递推式,解特征根只能用
f
2
,
f
3
f_2,f_3
f2,f3及以上
解出是
(
c
−
1
)
n
+
(
−
1
)
n
(
c
−
1
)
(c-1)^n+(-1)^n(c-1)
(c−1)n+(−1)n(c−1)
然后考虑对每个集合,计算强制集合内颜色相同并强制与其他集合不同的方案数
然后发现转移就是子集卷积
c
c
c次幂
直接搞就是了
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readll(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
cs int mod=1e9+7,phi=mod-1;
inline int add(int a,int b){return (a+b>=mod)?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
cs int N=25,M=(1<<20)|1;
int f[M][N],lg[M],cnt[M],ok[M];
int wy[N][2],iv[N],lk[N][N],id[N],ps[N];
int m,c,k,lim;
ll a[N],n;
inline bool comp(int i,int j){return a[i]<a[j];}
inline void Ln(int *f,int lim){
static int g[N];
memset(g,0,sizeof(g));
for(int i=0;i<lim;i++){
g[i]=mul(f[i+1],i+1);
for(int j=0;j<i;j++)Dec(g[i],mul(g[j],f[i-j]));
}
for(int i=lim;i;i--)f[i]=mul(g[i-1],iv[i]),g[i-1]=0;
f[0]=0;
}
inline void Exp(int *f,int lim){
static int g[N];
memset(g,0,sizeof(g));
for(int i=1;i<=lim;i++)Mul(f[i],i);
g[0]=1;
for(int i=0;i<lim;i++){
int res=0;
for(int j=0;j<=i;j++)Add(res,mul(f[j+1],g[i-j]));
g[i+1]=mul(res,iv[i+1]);
}
for(int i=lim;~i;i--)f[i]=g[i],g[i]=0;
}
inline void pksm(int *f,int b,int lim){
Ln(f,lim);
for(int i=0;i<=lim;i++)Mul(f[i],b);
Exp(f,lim);
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=readll(),k=read(),m=read(),c=readll()%mod;
int Iv=Inv(c);iv[0]=iv[1]=1;lim=1<<k;
for(int i=2;i<N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
for(int i=0;i<k;i++)a[i]=readll(),id[i]=i;
// cout<<"ok\n";
sort(id,id+k,comp);
for(int i=0;i<k;i++)ps[id[i]+1]=i;
// cout<<"Fc\n";
for(int i=0;i<k;i++){
ll dis=a[id[(i+1)%k]]-a[id[i]];
if(i+1==k)dis+=n;
wy[i][0]=mul(Iv,add(ksm(c-1,dis%phi),(dis&1)?dec(1,c):dec(c,1)));
wy[i][1]=mul(Iv,dec(ksm(c-1,dis%phi),(dis&1)?mod-1:1));
// cout<<wy[i][0]<<" "<<wy[i][1]<<'\n';
}
for(int i=1;i<=m;i++){
int u=ps[read()],v=ps[read()];
lk[u][v]=lk[v][u]=1;
}
f[0][0]=1,ok[0]=1;
for(int i=1;i<lim;i++)cnt[i]=cnt[i>>1]+(i&1);
for(int i=0;i<=k;i++)lg[1<<i]=i;
for(int s=1;s<lim;s++){
int u=lg[(s&(-s))];
if(!ok[s^(1<<u)])continue;
ok[s]=1;
for(int i=u+1;i<k;i++)
if((s&(1<<i))&&lk[u][i])
{ok[s]=0;break;}
if(!ok[s])continue;
int res=1;
for(int i=0;i<k;i++)if((s>>i)&1)
Mul(res,wy[i][((s>>((i+1)%k))&1)^1]);
f[s][cnt[s]]=res;
}
for(int mid=1;mid<lim;mid<<=1)
for(int i=0;i<lim;i+=mid<<1)
for(int j=0;j<mid;j++)
for(int s=0;s<=k;s++)
Add(f[i+j+mid][s],f[i+j][s]);
int res=0;
for(int s=0;s<lim;s++){
pksm(f[s],c,k);
if((k-cnt[s])&1)Dec(res,f[s][k]);
else Add(res,f[s][k]);
}cout<<res<<'\n';return 0;
}