【CSP-S 2019模拟】题解

T1:

显然可以用之前有次cspcsp模拟的方法,在转移出去的里面选方案最大的作为重儿子倍增

由于T3T3写太久了
根本没时间写

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first 
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0;bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
inline ll readl(){
	char ch=gc();
	ll res=0;bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline void Add(int &a,int b){a+=b,a>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?(r%mod):r;}
inline void Mul(int &a,int b){static ll r;r=1ll*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;}
cs ll inf=1e18+5;
inline ll fix(ll a){
	return a<inf?a:inf;
}
cs int N=50005,M=21,L=17;
ll f[N][M],vl[L][N][M],vr[L][N][M];
int v[L][N][M];
int nxt[L][N][M];
int pw[M],p[N][10];
char s[N],t[N];
int n,q,m,fail[N],tr[N][10];
inline void init(){
	for(int i=0,j=2;j<=m;j++){
		while(i&&s[i+1]!=s[j])i=fail[i];
		if(s[i+1]==s[j])i++;
		fail[j]=i;
	}
	for(int i=0;i<m;i++){
		for(int c=0;c<=9;c++){
			int p=i;
			while(p&&s[p+1]!=c+'0')p=fail[p];
			if(s[p+1]==c+'0')p++;
			tr[i][c]=p;
		}
	}
	for(int i=0;i<=9;i++)tr[m][i]=m;
	for(int i=1;i<=n;i++){
		if(t[i]=='?')for(int c=0;c<=9;c++)p[i][c]=1;
		else for(int c=0;c<=9;c++)p[i][c]=(c+'0'==t[i]);
	}
	for(int i=1;i<m;i++)f[n+1][i]=0;f[n+1][m]=1;
	for(int i=n;i;i--){
		for(int j=0;j<=m;j++){
			f[i][j]=0;
			ll mx=-1,hs=-1;
			for(int k=0;k<=9;k++)if(p[i][k]){
				f[i][j]=fix(f[i][j]+f[i+1][tr[j][k]]);
				if(f[i+1][tr[j][k]]>mx)mx=f[i+1][tr[j][k]],hs=k;
			}
			nxt[0][i][j]=tr[j][hs],v[0][i][j]=hs,vl[0][i][j]=0;
			for(int k=0;k<hs;k++)if(p[i][k])vl[0][i][j]=fix(vl[0][i][j]+f[i+1][tr[j][k]]);
			vr[0][i][j]=fix(vl[0][i][j]+f[i+1][tr[j][hs]]);
		}
	}
	for(int k=1;k<=16;k++){
		int l=1<<(k-1);
		for(int i=1;i+(1<<k)<=n+1;i++)
		for(int j=0;j<=m;j++){
			int x=nxt[k-1][i][j];
			nxt[k][i][j]=nxt[k-1][i+l][x];
			v[k][i][j]=add(mul(v[k-1][i][j],pw[k-1]),v[k-1][i+l][x]);
			vl[k][i][j]=fix(vl[k-1][i][j]+vl[k-1][i+l][x]);
			vr[k][i][j]=fix(vl[k-1][i][j]+vr[k-1][i+l][x]);
		}
	}
}
inline int dfs(ll k){
	if(k>f[1][0])return -1;
	int p=1,c=0,res=0;
	while(p<=n){
		for(int i=16;~i;i--){
			if(p+(1<<i)<=n+1&&vl[i][p][c]<k&&k<=vr[i][p][c]){
				Mul(res,pw[i]),Add(res,v[i][p][c]);
				k-=vl[i][p][c],c=nxt[i][p][c],p+=1<<i;
			}
		}
		if(p>n)break;
		for(int i=0;i<=9;i++){
			if(k>f[p+1][tr[c][i]])k-=f[p+1][tr[c][i]];
			else{
				Mul(res,10),Add(res,i),p++,c=tr[c][i];break;
			}
		}
	}
	return res;
}
inline void solve(){
	n=read(),q=read();
	scanf("%s",s+1);
	m=strlen(s+1);
	scanf("%s",t+1);
	init();
	while(q--){
		cout<<dfs(readl())<<'\n';
	}
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	freopen("my.out","w",stdout);
	#endif
	pw[0]=10;
	for(int i=1;i<L;i++)pw[i]=mul(pw[i-1],pw[i-1]);
	int T=read();
	while(T--)solve();
}

T2:

考虑对于每个大小2i2^i维护纯色块个数cnticnt_i
那么答案其实是i(2ni)i4cnti\sum_{i}(2^{n-i})^i-4*cnt_i
就是对于一个纯色块,不会继续递归
那么减去递归会增加的贡献即可
发现纯色块对于x,yx,y独立
维护x,yx,y2i2^i纯色子区间个数
乘起来就是答案

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first 
#define se second
#define ll long long
cs int RLEN=1<<20|1;
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+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=(1<<21)+15;
char xxx;
int n,q,lim;
struct Seg{
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	int v[22],s[N<<2];
	void build(int u,int l,int r,int dep){	
		if(l==r)return;
		v[dep]++;
		build(lc,l,mid,dep-1),build(rc,mid+1,r,dep-1);
	}
	void update(int u,int l,int r,int dep,int p){
		if(l==r){s[u]^=1;return;}
		if(p<=mid)update(lc,l,mid,dep-1,p);
		else update(rc,mid+1,r,dep-1,p);
		int pre=s[u];s[u]=s[lc]+s[rc];
		if((pre==0&&s[u]==1)||(pre==r-l+1&&s[u]==r-l))v[dep]--;
		if((pre==1&&s[u]==0)||(pre==r-l&&s[u]==r-l+1))v[dep]++;
	}
	#undef lc
	#undef rc
	#undef mid
}t1,t2;
char yyy;
int main(){
	#ifdef Stargazer
	freopen("lx.cpp","r",stdin);
	#endif
	n=read(),lim=(1<<n),q=read();
	t1.build(1,1,lim,n);
	t2.build(1,1,lim,n);
	while(q--){
		int op=read(),x=read();
		if(op==0)t1.update(1,1,lim,n,x);
		else t2.update(1,1,lim,n,x);
		ll res=0;
		for(int i=0;i<=n;i++)
			res+=(1ll<<((n-i)*2))-4ll*t1.v[i]*t2.v[i];
		cout<<res<<'\n';
	}
}

T3:

stdstd正解用到了平面图的特殊性质
实际上我根本没看到那句话
而我这个可以对不是平面图的一样做

对于一边不断删去点,另一边的一定是不断加点
这样可以双指针+LCT+LCT暴力维护
然后要中间的点在同一个联通块
把中间点权值设为11,看一棵树权值和是否为nn
于是乎需要维护一下虚子树的sumsum
还有个问题是虽然上下都是树
但是可能连一起出现环

所以还要维护一下一个环上最下面的边
如果上面要连时已经连通的时候要把环上最下面的一条边断开
于是还需要化边为点来维护一个maxposmaxpos

然后随便写写
反正我光写就写了一个多小时
还因为写错一个小地方爆零了
mmpmmp

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first 
#define se second
#define ll long long
cs int RLEN=1<<20|1;
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+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=800005;
char xxx;
int n,m1,m2,tim[N];
vector<pii>e1[N],e2[N];
struct pt{
	int x,y;
}p[N];
namespace Lct{
	cs int M=800005;
	int val[M],rev[M],s[M],c[M],mx[M],xs[M],tot,fa[M],son[M][2];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline bool isrt(int u){
		return !fa[u]||(rc(fa[u])!=u&&lc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	inline void pushup(int u){
		s[u]=(u<=n)+xs[u];
		mx[u]=c[u];
		if(lc(u)){
			s[u]+=s[lc(u)];
			if(tim[mx[lc(u)]]>tim[mx[u]])mx[u]=mx[lc(u)];
		}
		if(rc(u)){
			s[u]+=s[rc(u)];
			if(tim[mx[rc(u)]]>tim[mx[u]])mx[u]=mx[rc(u)];
		}
	}
	inline void pushnow(int u){
		swap(lc(u),rc(u)),rev[u]^=1;
	}
	inline void pushdown(int u){
		if(!rev[u])return;
		if(lc(u))pushnow(lc(u));
		if(rc(u))pushnow(rc(u));
		rev[u]=0;
	}
	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;
		fa[u]=v,son[v][t^1]=u;
		pushup(u),pushup(v);
	}
	int stk[N],top;
	inline void splay(int u){
		stk[top=1]=u;
		for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
		for(int i=top;i;i--)pushdown(stk[i]);
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
			rotate(u);
		}
		pushup(u);
	}
	inline void access(int u){
		for(int v=0;u;v=u,u=fa[u]){
			splay(u);
			if(rc(u))xs[u]+=s[rc(u)];
			if(v)xs[u]-=s[v],fa[v]=u;
			rc(u)=v,pushup(u);
		}
	}
	inline int findrt(int u){
		access(u),splay(u);
		while(pushdown(u),lc(u))u=lc(u);
		splay(u);return u;
	}
	inline void makert(int u){
		access(u),splay(u),pushnow(u);
	}
	inline void link(int u,int v){
		access(u),splay(u),makert(v),fa[v]=u,xs[u]+=s[v];
		pushup(u);
	}
	inline void cut(int u,int v){
		makert(u),access(v),splay(v);
		fa[lc(v)]=0,lc(v)=0,pushup(u),pushup(v);
	}
	inline int querysize(int u){
		access(u),splay(u);return s[u];
	}
	inline int querypos(int u,int v){
		makert(u),access(v),splay(v);
		return mx[v];
	}
}
using namespace Lct;
int a[N],b[N],cnt1,cnt2;
int pos1[N],pos2[N],pe1[N],pe2[N];
vector<int>p1[N],p2[N];
pii E1[N],E2[N];
ll sum[N];
inline ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
inline void cutedge(int id){
	int u=E2[id].fi,v=E2[id].se;
	if(findrt(u)==findrt(pe2[id])){
		cut(u,pe2[id]);
	}
	if(findrt(v)==findrt(pe2[id])){
		cut(v,pe2[id]);
	}
}
inline void deletnode(int u){
	for(int i=0;i<e2[u].size();i++){
		int id=e2[u][i].se;
		cutedge(id);
	}
}
inline void insertnode(int u){
	for(int i=0;i<e1[u].size();i++){
		int v=e1[u][i].fi,id=e1[u][i].se;
		if(findrt(u)==findrt(v)){
			int pos=querypos(u,v);
			cutedge(pos);
		}
		link(v,pe1[id]),link(u,pe1[id]);
	}
}
char yyy;
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m1=read(),m2=read();
	for(int i=1;i<=n;i++)val[++tot]=1,pushup(tot);
	for(int i=1;i<=m1;i++)pos1[i]=++tot;
	for(int i=1;i<n+m1;i++)pe1[i]=++tot;
	for(int i=1;i<=m1;i++){
		p[i].x=read(),p[i].y=read();
		a[i]=p[i].y;
	}
	sort(a+1,a+m1+1);
	cnt1=unique(a+1,a+m1+1)-a-1;
	for(int i=1;i<=m1;i++){
		p[i].y=lower_bound(a+1,a+cnt1+1,p[i].y)-a;
		p1[p[i].y].pb(pos1[i]);
	}
	for(int i=cnt1;i;i--)sum[i]=sum[i+1]+(ll)p1[i].size();
	for(int i=1;i<n+m1;i++){
		int op=read(),v=read(),u=read();
		if(op==2){
			if(p[u].y<p[v].y)swap(u,v);
			v=pos1[v];
		}
		u=pos1[u];
		e1[u].pb(pii(v,i));
		E1[i]=pii(u,v);
	}
	for(int i=1;i<=m2;i++){
		p[i].x=read(),p[i].y=-read();
		a[i]=p[i].y;
	}
	for(int i=1;i<=m2;i++)pos2[i]=++tot;
	for(int i=1;i<n+m2;i++)pe2[i]=++tot;
	sort(a+1,a+m2+1);
	cnt2=unique(a+1,a+m2+1)-a-1;
	for(int i=1;i<=m2;i++){
		p[i].y=lower_bound(a+1,a+cnt2+1,p[i].y)-a;
		p2[p[i].y].pb(pos2[i]);
	}
	for(int i=1;i<n+m2;i++){
		int op=read(),v=read(),u=read();
		if(op==2&&p[u].y<p[v].y)swap(u,v);
		tim[i]=p[u].y;
		c[pe2[i]]=i;pushup(pe2[i]);
		u=pos2[u];if(op==2)v=pos2[v];		
		E2[i]=pii(u,v);
		if(op==1){
			link(u,pe2[i]),link(v,pe2[i]);
		}
		else {
			link(u,pe2[i]),link(v,pe2[i]);
		}
		e2[u].pb(pii(v,i));
	}
	ll res=0;
	for(int i=cnt2,j=1;i;i--){
		for(int t=0;t<p2[i].size();t++){
			int u=p2[i][t];
			deletnode(u);
		}
		while(querysize(1)<n&&j<=cnt1){
			for(int t=0;t<p1[j].size();t++){
				int u=p1[j][t];
				insertnode(u);
			}
			j++;
		}
		res+=1ll*p2[i].size()*sum[j];
	}
	ll all=1ll*m2*m1;
	ll g=gcd(all,res);
	all/=g,res/=g;
	if(!res)puts("0");
	else if(all==res)puts("1");	
	else cout<<res<<"/"<<all<<'\n';
	return 0;
}
posted @ 2019-11-05 18:30  Stargazer_cykoi  阅读(160)  评论(0编辑  收藏  举报