• 【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())<<'
    ';
    	}
    }
    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)i4cntisum_{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<<'
    ';
    	}
    }
    

    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<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    Windows 10 开发日记(二)-- 手势顺序调研
    Windows 10 开发日记(一) -- 手势通览
    开篇说两句
    我从上海回苏州了,你懂的!
    数组名相关
    指针相关笔记
    static相关
    输入分式,输出化简式的C语言算法
    语句界定
    switch相关
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328369.html
Copyright © 2020-2023  润新知