- O(nlog2n) 即考虑从大到小加入数,维护一下最长连续区间
- 考虑预处理 li,ri 表示最小值的管辖区间,那么对于询问 [L,R] 就是求所有与其交不小于 w 的最大值,考虑 li<L,和 li∈[L,R−w+1],是简单的二维数点问题,O(nlogn)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pi;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
} int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
}
} using namespace IO;
cs int N = 1e6 + 50;
cs int INF = 1e9 + 7;
void ckmax(int &a, int b){ if(a < b) a = b; }
int n, m, a[N], l[N], r[N], ans[N];
namespace bit{
int c[N];
void add(int x, int v){ for(;x;x-=x&-x) ckmax(c[x],v); }
int ask(int x){ int as=0; for(;x<=n;x+=x&-x) ckmax(as,c[x]); return as; }
}
namespace zkw{
cs int M = 1 << 20; int mx[M<<1];
void ins(int x, int v){ for(x+=M;x;x>>=1) ckmax(mx[x],v); }
int qry(int l, int r){
int as=0; for(l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){
if(l&1^1) ckmax(as,mx[l^1]);
if(r&1) ckmax(as,mx[r^1]);
} return as;
}
}
vector<pi> G[N];
vector<pi> v[N];
struct qry{ int l, r, w, c; } q[N];
bool cmpw(cs qry &a, cs qry &b){ return a.w > b.w; }
bool cmp(cs int &a, cs int &b){ return r[a]-l[a] > r[b]-l[b]; }
int main(){
#ifdef FSYolanda
freopen("a.in","r",stdin);
freopen("tmp.out","w",stdout);
#endif
n=read();
for(int i=1; i<=n; i++) a[i]=read();
static int sta[N]; int top=0;
for(int i=1; i<=n; i++){
while(top&&a[sta[top]]>=a[i]) r[sta[top]]=i, --top;
l[i]=sta[top]; sta[++top]=i;
} while(top) r[sta[top]]=n+1, --top;
m=read();
for(int i=1,l,r,w; i<=m; i++)
l=read(), r=read(), w=read(),
v[l].pb(mp(l+w-1,i)), q[i]=(qry){l,r,w,i};
for(int i=1; i<=n; i++) ++l[i], --r[i], G[l[i]].pb(mp(r[i],a[i]));
for(int i=1; i<=n; i++){
for(int e=0; e<G[i].size(); e++)
bit::add(G[i][e].fi, G[i][e].se);
for(int e=0; e<v[i].size(); e++)
ckmax(ans[v[i][e].se], bit::ask(v[i][e].fi));
}
static int id[N];
for(int i=1; i<=n; i++) id[i]=i;
sort(id+1,id+n+1,cmp);
sort(q+1,q+m+1,cmpw);
for(int i=1,j=1; i<=m; i++){
while(j<=n && r[id[j]]-l[id[j]]+1 >= q[i].w)
zkw :: ins(l[id[j]],a[id[j]]), ++j;
ckmax(ans[q[i].c], zkw :: qry(q[i].l, q[i].r-q[i].w+1));
} for(int i=1; i<=m; i++) cout<<ans[i]<<'\n';
return 0;
}
- 考虑将子树 max 最大的作为重儿子,那么这个过程类似 access
再用一棵平衡树维护虚子树,需要支持删除和前端插入以及维护权值,还需要维护虚子树的 size
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pi;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
} int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
}
} using namespace IO;
cs int N = 2e5 + 50;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
int n, m, pw[N];
namespace Splay{
int ch[N][2], fa[N], sz[N], sm[N], vl[N], tz[N];
void init(int x, int a, int b){
sz[x] = tz[x] = b;
vl[x] = sm[x] = a;
sz[x+n] = tz[x+n] = vl[x+n] = sm[x+n] = 0;
} void clr(int x, int a, int b){
sz[x] = tz[x] = b;
vl[x] = sm[x] = a; ch[x][0] = ch[x][1] = fa[x] = 0;
}
void up(int x){
sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + tz[x];
sm[x] = sm[ch[x][0]]; Add(sm[x],mul(pw[sz[ch[x][0]]],vl[x]));
Add(sm[x],mul(pw[sz[ch[x][0]]+tz[x]],sm[ch[x][1]]));
} int get(int x){ return ch[fa[x]][1]==x; }
void rot(int x){
int y=fa[x], z=fa[y], k=get(x);
assert(y);
if(z) ch[z][get(y)]=x; fa[x]=z;
ch[y][k]=ch[x][k^1]; fa[ch[x][k^1]]=y;
ch[x][k^1]=y; fa[y]=x; up(y); up(x);
} void spl(int x, int gl=0){
while(fa[x]!=gl){
int y=fa[x]; if(fa[y]!=gl)
rot(get(x)^get(y)?x:y); rot(x);
}
}
int ins(int rt, int x, int a, int b){
rt=rt+n; clr(x,a,b);
int t=rt; while(ch[t][0]) t=ch[t][0];
fa[x]=t; ch[t][0]=x; up(t);
spl(x); spl(rt); return sm[rt];
} int del(int rt, int x){
rt=rt+n; spl(x); int t=ch[x][1];
while(ch[t][0]) t=ch[t][0]; spl(t,x);
ch[t][0]=ch[x][0]; fa[ch[x][0]]=t;
fa[x]=fa[t]=ch[x][0]=ch[x][1]=0;
up(t); spl(rt); return sm[rt];
}
}
namespace LCT{
int ch[N][2], fa[N], sz[N], iz[N], vl[N], ivl[N];
void init(int u){ vl[u]=u; sz[u]=1; Splay::init(u,u,1); }
bool isr(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; }
int get(int x){ return ch[fa[x]][1]==x; }
void up(int x){
vl[x]=add(ivl[x],mul(x,pw[iz[x]]));
sz[x]=iz[x]+sz[ch[x][1]]+1;
vl[x]=add(vl[ch[x][1]],mul(pw[sz[ch[x][1]]],vl[x]));
Add(vl[x],mul(vl[ch[x][0]],pw[sz[x]])); sz[x]+=sz[ch[x][0]];
} void rot(int x){
int y=fa[x], z=fa[y], k=get(x);
if(!isr(y)) ch[z][get(y)]=x; fa[x]=z;
ch[y][k]=ch[x][k^1]; fa[ch[x][k^1]]=y;
ch[x][k^1]=y; fa[y]=x; up(y); up(x);
} void spl(int x){
while(!isr(x)){
int y=fa[x]; if(!isr(y))
rot(get(x)^get(y)?x:y); rot(x);
}
}
int fnd(int x){ while(ch[x][0]) x=ch[x][0]; return x; }
void acs(int u){
int y=0; for(int x=u;x;y=x,x=fa[x]){
spl(x);
if(ch[x][1]){
iz[x] += sz[ch[x][1]]; int tr = fnd(ch[x][1]);
ivl[x] = Splay::ins(x,fnd(ch[x][1]),vl[ch[x][1]],sz[ch[x][1]]);
} if(y){
iz[x] -= sz[y];
ivl[x] = Splay::del(x,fnd(y));
} ch[x][1] = y; up(x);
}
}
void work(int u){
init(u); acs(fa[u]); spl(fa[u]);
++iz[fa[u]]; ivl[fa[u]] = Splay::ins(fa[u],u,vl[u],sz[u]); acs(u);
} int qry(){ return spl(1),vl[1]; }
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
n=read(); pw[0]=1; pw[1]=257933;
for(int i=2; i<=n; i++) pw[i]=mul(pw[i-1],pw[1]);
LCT::init(1);
for(int i=2; i<=n; i++)
LCT::fa[i]=read(), LCT::work(i), cout<<LCT::qry()<<'\n';
return 0;
}
- 令 f0,f1 表示和开头相同或是不同的方案数
fi,0=fi−1,1,fi,1=fi−1,0(c−1)+fi−1,1(c−2)
可以解出,fi,1=(c−1)i+(−1)i(c−1)
求出 fS 表示钦定 S 中颜色相同,并强制 S 外与其颜色不同的方案数,要求 S 中两两不连边
那么最后的答案就是 [xU]fc,子集卷积即可(先对集合转点值然后对 bitcnt 做正常卷积)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,Mul(a,a)) if(b&1) Mul(as,a); return as; }
typedef long long ll;
cs int N = 22, M = 1 << 20 | 5;
ll a[N], n, m, c, ic, S; int k, e[N], es[M];
bool cmp(cs int &i, cs int &j){ return a[i] < a[j]; }
int coe[N][2], f[M][N], iv[M];
void ln(int *f){
static int g[N]; memset(g,0,sizeof(g));
for(int i=0; i<k; i++){
g[i]=mul(i+1,f[i+1]);
for(int j=0; j<i; j++) Dec(g[i],mul(f[i-j],g[j]));
} for(int i=k; i>=1; i--) f[i]=mul(g[i-1],iv[i]); f[0]=0;
}
void Exp(int *f){
static int g[N]; memset(g,0,sizeof(g));
for(int i=1; i<=k; i++) Mul(f[i],i); g[0]=1;
for(int i=0; i<k; i++){
for(int j=0; j<=i; j++) Add(g[i+1],mul(f[j+1],g[i-j]));
Mul(g[i+1],iv[i+1]);
} for(int i=1; i<=k; i++) f[i]=g[i]; f[0]=1;
}
void poly_pw(int *f){ ln(f); for(int i=0; i<=k; i++) Mul(f[i],c); Exp(f); }
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%lld%d%lld%lld",&n,&k,&m,&c); c %= Mod;
ic=ksm(c,Mod-2); iv[0]=iv[1]=1; S = 1<<k;
for(int i=2; i<=S; i++) iv[i]=mul(Mod-Mod/i,iv[Mod%i]);
static int id[N], p[N];
for(int i=0; i<k; i++) scanf("%lld",&a[i]), id[i]=i;
sort(id, id+k, cmp);
for(int i=0; i<k; i++) p[id[i]] = i;
for(int i=0; i<k; i++){
ll d=a[id[(i+1)%k]]-a[id[i]];
if(i+1==k) d+=n;
coe[i][0]=mul(ic,add(ksm(c-1,d%(Mod-1)),(d&1)?dec(1,c):dec(c,1)));
coe[i][1]=mul(ic,add(ksm(c-1,d%(Mod-1)),(d&1)?1:-1));
}
for(int i=1,u,v; i<=m; i++){
scanf("%d%d",&u,&v); u=p[u-1], v=p[v-1];
e[u]|=1<<v; e[v]|=1<<u;
} for(int i=0; i<S; i++)
for(int j=0; j<k; j++) if(i>>j&1) es[i]|=e[j];
static int bin[M];
for(int i=0; i<S; i++) bin[i]=bin[i>>1]+(i&1);
f[0][0] = 1;
for(int i=1; i<S; i++){
if(es[i] & i) continue; int way = 1;
for(int j=0; j<k; j++) if(i>>j&1)
Mul(way,coe[j][(i>>((j+1)%k)&1)^1]);
f[i][bin[i]] = way;
}
for(int i=1; i<S; i<<=1)
for(int j=0; j<S; j+=(i<<1))
for(int e=0; e<i; e++)
for(int o=0; o<=k; o++)
Add(f[i+j+e][o],f[j+e][o]);
for(int i=0; i<S; i++) poly_pw(f[i]);
for(int i=1; i<S; i<<=1)
for(int j=0; j<S; j+=(i<<1))
for(int e=0; e<i; e++)
Dec(f[i+j+e][k],f[j+e][k]);
cout<<f[S-1][k]; return 0;
}