【2020省选模拟】题解

T1:

对树分层 d p dp dp即可
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]从大到小第 i i i个, j j j个当前层的点, k k k个下一层的点
要么选一个当前层,要么当前层全部拆到下和下下层

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{

cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
	(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=0;
	while(!isdigit(ch))f=ch=='-',ch=gc();
	while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
	return f?-res:res;
}

}
using IO::read;
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=755;
int a[N],s[N],n;
ll f[N][N],inf;
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	sort(a+1,a+n+1,greater<int>());
	for(int i=n;i;i--)s[i]=s[i+1]+a[i];
	memset(f,127/3,sizeof(f));inf=f[0][0];
	f[1][1]=s[1];
	for(int i=1;i<=n;i++){
		int vl=s[i];
		for(int j=0,l=n-i+1;j<=l;j++)
		for(int k=0,l2=n-i+1-j;k<=l2;k++){
			chemn(f[j+k][j],f[j][k]+vl);
		}
		for(int j=1,l=n-i+1;j<=l;j++)
		for(int k=0,l2=n-i+1-j;k<=l2;k++)
		f[j-1][k]=f[j][k];
	}
	cout<<f[0][0];return 0;
}

T2:

神必东西
实际上记左右第一个断点和上一个似乎可以 d p dp dp?
但感觉不可能有人写的出来

考虑两个11之间一定不可达,然后全赋成1
然后这样状态莫名就很少了

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{

cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
	(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=0;
	while(!isdigit(ch))f=ch=='-',ch=gc();
	while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
	return f?-res:res;
}
inline void readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return;
}

}
using IO::read;
using IO::readstring;
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;}

int mod;
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){return (ll)a*b%mod;}
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){a=(ll)a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))if(b&1)Mul(res,a);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
typedef unsigned long long ul;
int n,iv4;
struct bt{
	ul a,b;
	bt():a(0),b(0){}
	bt(ul _a,ul _b):a(_a),b(_b){}
	void set(int i){(i<64?a:b)|=1ull<<(i&63);}
	bool get(int i)cs{return ((i<64?a:b)>>(i&63))&1;}
	bt operator >>(int i)cs{
		if(i<64)return bt(((b&((1ull<<i)-1))<<(64-i))|(a>>i),b>>i);
		return bt(b>>(i-64),0);
	}
	bt operator <<(int i)cs{
		if(i<64)return bt(a<<i,(b<<i)|(a>>(64-i)));
		return bt(0,a<<(i-64));
	}
	bt operator |(cs bt &x)cs{return bt(a|x.a,b|x.b);}
	bt operator &(cs bt &x)cs{return bt(a&x.a,b&x.b);}
	bt operator &(int x)cs{return bt(a&x,0);}
	bt resize()cs{
		if(n<64)return bt(a&((1ull<<n)-1),0);
		if(n==64)return *this;
		return bt(a,b&((1ull<<(n-64))-1));
	}
	bt rever()cs{
		bt x;if(get(0))x.set(0);
		for(int i=1;i<n;i++)if(get(i))x.set(n-i);
		return x;
	}
	bool operator <(cs bt &x)cs{
		return (b==x.b)?(a<x.a):b<x.b;
	}
	void cover(){
		int l=n+1,r=-1;
		for(int i=1;i+1<n;i++)
		if(get(i)&&get(i+1))l=min(i,l),r=max(i,r);
		if(l+2>=r)return;
		for(int i=l;i<=r+1;i++)set(i);
	}
};
map<bt,int>f;
bt move(bt x,int k){
	switch(k){
		case 1:return (x>>1)|((x&1)<<(n-1));
		case 2:return (x>>2)|((x&3)<<(n-2));
		case -1:return ((x<<1)|(x>>(n-1))).resize();
		case -2:return ((x<<2)|(x>>(n-2))).resize();
	}
}
int dfs(bt x){
	if(x.get(0))return 0;
	x.set(0),x.cover();
	x=min(x,x.rever());
	if(f.count(x))return f[x];
	int res=0;
	Add(res,dfs(move(x,1)));
	Add(res,dfs(move(x,2)));
	Add(res,dfs(move(x,-1)));
	Add(res,dfs(move(x,-2)));
	Mul(res,iv4);
	return f[x]=res+1;
}
int main(){
	cin>>n>>mod;iv4=Inv(4);
	if(n==1)return cout<<1,0;
	cout<<dfs(bt());
}

T3:

在回文树上树剖维护即可
注意先求出每个位置的最长回文前后缀所在的点
这需要离线建出 p a m pam pam后前后后前分别跑一次

还有特殊处理一下 l c a lca lca是不是最长后缀
由于考试时脑残写的双向 p a m pam pam懒得改了

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{

cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
	(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=0;
	while(!isdigit(ch))f=ch=='-',ch=gc();
	while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
	return f?-res:res;
}
inline void readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return;
}

}
using IO::read;
using IO::readstring;
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=3e5+5;
int L,R,cnt,n,q,tot;
int s[N];
int pl[N],pr[N],pos[N];
struct opt{
	int a,b,c,d;
}qy[N];
int pt[N],kd[N];
pii qt[N];
vector<int> e[N],pre;
int fa[N],len[N],in[N],dfn,id[N],dep[N],siz[N],son[N],top[N];
namespace seg{
	
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
cs int N=::N<<2;
ll coef[N],tag[N],sm[N];
void pushnow(int u,ll k){
	tag[u]+=k,sm[u]+=coef[u]*k;
}
void pushdown(int u){
	if(!tag[u])return;
	pushnow(lc,tag[u]);
	pushnow(rc,tag[u]);
	tag[u]=0;
}
void build(int u,int l,int r){
	if(l==r){coef[u]=len[id[l]];return;}
	build(lc,l,mid),build(rc,mid+1,r);
	coef[u]=coef[lc]+coef[rc];
}
void update(int u,int l,int r,int st,int des,int k){
	if(st<=l&&r<=des)return pushnow(u,k);
	pushdown(u);
	if(st<=mid)update(lc,l,mid,st,des,k);
	if(mid<des)update(rc,mid+1,r,st,des,k);
	sm[u]=sm[lc]+sm[rc];
}
ll query(int u,int l,int r,int st,int des){
	if(st<=l&&r<=des)return sm[u];
	pushdown(u);ll res=0;
	if(st<=mid)res+=query(lc,l,mid,st,des);
	if(mid<des)res+=query(rc,mid+1,r,st,des);
	return res;
}
#undef lc
#undef rc
#undef mid

}
void dfs(int u){
	siz[u]=1;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(v==fa[u])continue;
		dep[v]=dep[u]+1,dfs(v),siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}
void dfs2(int u,int tp){
	in[u]=++dfn,id[dfn]=u,top[u]=tp;
	if(son[u])dfs2(son[u],tp);
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(v==fa[u]||v==son[u])continue;
		dfs2(v,v);
	}
}
inline int find(int u,int k){
	while(len[top[u]]>k)u=fa[top[u]];
	int l=in[top[u]],r=in[u],res=l;
	while(l<=r){
		int mid=(l+r)>>1;
		if(len[id[mid]]<=k)l=mid+1,res=mid;
		else r=mid-1;
	}return id[res];
}
namespace pam{

int nxt[N][26],lastl,lastr,fa[N],len[N];
inline void init(){
	memset(s,-1,sizeof(s));
	len[1]=-1,fa[0]=1;tot=1;
}
inline int find(int p,int d){
	if(d==0){
		while(s[R]!=s[R-len[p]-1])p=fa[p];return p;
	}
	while(s[L]!=s[L+len[p]+1])p=fa[p];return p;
}
inline void getpos(){
	int p=0;int nl=L,nr=R;
	for(R=nl;R<=nr;R++){
		p=nxt[find(p,0)][s[R]];
		pl[R]=p;
	}
	p=0;
	for(L=nr;L>=nl;L--){
		p=nxt[find(p,1)][s[L]];
		pr[L]=p;
	}L=nl,R=nr;
}
void insert(int c,int d,int ps){
	int p=find(d?lastl:lastr,d);
	if(!nxt[p][c]){
		int u=++tot;
		len[u]=len[p]+2;
		fa[u]=nxt[find(fa[p],d)][c];
		nxt[p][c]=u;
	}
	if(d==0){
		lastr=nxt[p][c];
		if(len[lastr]==R-L+1)lastl=lastr;
		if(ps)pos[ps]=lastr+1;
		else pre.pb(lastr+1);
	}
	else{
		lastl=nxt[p][c];
		if(len[lastl]==R-L+1)lastr=lastl;
		if(ps)pos[ps]=lastl+1;
		else pre.pb(lastl+1);
	}
}

}
char op[10];
inline int Lca(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		u=fa[top[u]];
	}return dep[u]<dep[v]?u:v;
}
void update(int u,int k){
	while(u){
		seg::update(1,1,tot,in[top[u]],in[u],k);
		u=fa[top[u]];
	}
}
ll query(int u,int v,int kd){
	ll res=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res+=seg::query(1,1,tot,in[top[u]],in[u]);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	if(in[v]+kd<=in[u])res+=seg::query(1,1,tot,in[v]+kd,in[u]);
	return res;
}
int main(){
	pam::init();L=1e5+1,R=1e5;
	n=read(),q=read();
	for(int i=1;i<=n;i++)s[++R]=read(),pam::insert(s[R],0,0);
	for(int i=1;i<=q;i++){
		readstring(op);
		if(op[1]=='a'){
			int c=read();
			if(op[4]=='l'){pt[i]=1;
				s[--L]=c,pam::insert(c,1,i);
			}
			else{pt[i]=2;
				s[++R]=c,pam::insert(c,0,i);
			}
		}
		else{
			int l1=L+read()-1,r1=L+read()-1,l2=L+read()-1,r2=L+read()-1;
			qy[i]=(opt){l1,r1,l2,r2};
			if(op[6]=='l')pt[i]=3;
			else pt[i]=4;
		}
	}
	pam::getpos();
//	for(int i=L;i<=R;i++)cout<<pl[i]<<" "<<pr[i]<<'\n';
	for(int i=0;i<=tot;i++)len[i+1]=pam::len[i],fa[i+1]=pam::fa[i]+1;
	tot++;fa[2]=0;len[2]=0;
	for(int i=1;i<=tot;i++)if(i!=2)e[fa[i]].pb(i);
	dfs(2),dfs2(2,2);
	for(int i=1;i<=q;i++)if(pt[i]==3||pt[i]==4){
		int l1=qy[i].a,r1=qy[i].b,l2=qy[i].c,r2=qy[i].d,p1,p2;
		if(pt[i]==3)p1=find(pl[r1]+1,r1-l1+1),p2=find(pl[r2]+1,r2-l2+1);
		else p1=find(pr[l1]+1,r1-l1+1),p2=find(pr[l2]+1,r2-l2+1);
		int l=len[Lca(p1,p2)];qt[i]=pii(p1,p2);
		if(pt[i]==3)kd[i]=(l1+l<=r1&&l2+l<=r2&&s[r1-l]==s[r2-l]);
		else kd[i]=(l1+l<=r1&&l2+l<=r2&&s[l1+l]==s[l2+l]);
	}
	seg::build(1,1,tot);
	for(int i=0;i<pre.size();i++)update(pre[i],1);
	for(int i=1;i<=q;i++){
		if(pt[i]<=2){
			update(pos[i],1);
		}
		else{
			cout<<query(qt[i].fi,qt[i].se,kd[i])<<'\n';
		}
	}return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值