【省选模拟】20/05/19

AA

  • O(nlog2n)O(n\log ^2n) 即考虑从大到小加入数,维护一下最长连续区间
  • 考虑预处理 li,ril_i,r_i 表示最小值的管辖区间,那么对于询问 [L,R][L,R] 就是求所有与其交不小于 ww 的最大值,考虑 li<Ll_i<L,和 li[L,Rw+1]l_i\in[L,R-w+1],是简单的二维数点问题,O(nlogn)O(n\log n)
#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;
}

BB

  • 考虑将子树 maxmax 最大的作为重儿子,那么这个过程类似 accessaccess
    再用一棵平衡树维护虚子树,需要支持删除和前端插入以及维护权值,还需要维护虚子树的 sizesize
#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;
}

CC

  • f0,f1f_0,f_1 表示和开头相同或是不同的方案数
    fi,0=fi1,1,fi,1=fi1,0(c1)+fi1,1(c2)f_{i,0}=f_{i-1,1},f_{i,1}=f_{i-1,0}(c-1)+f_{i-1,1}(c-2)
    可以解出,fi,1=(c1)i+(1)i(c1)f_{i,1}=(c-1)^i+(-1)^{i}(c-1)
    求出 fSf_{S} 表示钦定 SS 中颜色相同,并强制 SS 外与其颜色不同的方案数,要求 SS 中两两不连边
    那么最后的答案就是 [xU]fc[x^{U}]f^c,子集卷积即可(先对集合转点值然后对 bitcntbitcnt 做正常卷积)
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章