【2020省选模拟】题解

T1:

处理出左右比他大的范围
然后分有没有覆盖分别维护一下即可
注意 z k w zkw zkw由于区间 [ l − 1 , r + 1 ] [l-1,r+1] [l1,r+1]所以处理到 M ≤ n + 1 M\le n+1 Mn+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=fn1(c2)+fn2(c1)
但是注意对于 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) (c1)n+(1)n(c1)

然后考虑对每个集合,计算强制集合内颜色相同并强制与其他集合不同的方案数
然后发现转移就是子集卷积 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值