国庆模拟赛四

T1

结论:直接输出TIE

T2

树剖,然后有古神的神奇结论:

1.对于一个查询只用管他两个链的端点的答案

2.建线段树之后两个点之间答案为他们左右儿子两两组合的较大值

就这样,还没改出来……毁灭吧

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls now<<1
#define rs now<<1|1
const ll N=114514,M=1919810;
struct xx{
	ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
	e[++cnt].next=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
ll dept[N],size[N],son[M],f[N];
ll dfn[N],st[N],to[N],t_cnt;
void dfs1(ll u,ll fa){
	size[u]=1;
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(v==fa) continue;
		dept[v]=dept[u]+1; f[v]=u;	
		dfs1(v,u);
		size[u]+=size[v];
		if(size[son[u]]<size[v]) son[u]=v;
	}
}
void dfs2(ll u,ll top){
	st[u]=top,dfn[u]=++t_cnt,to[t_cnt]=u;
	if(son[u]) dfs2(son[u],top);
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(dfn[v]) continue;
		dfs2(v,v);
	}
}
ll query_lca(ll u,ll v){
	while(st[u]!=st[v]){
		if(dept[st[u]]<dept[st[v]]) swap(u,v);
		u=f[st[u]];
	}
	if(dept[u]>dept[v]) swap(u,v);
	return u;
}
ll n,q;
struct gx{
	ll u,v;
}ys[N];
struct tree{
	ll l,r,lca,val;
	bool operator <(const tree &lxl)const{
		return val<lxl.val;
	}
	tree(){l=r=lca=val=0;}
}t[4*N];
/*古神的神奇结论:
1.对于一个查询只用管他两个链的端点的答案
2.建线段树之后两个点之间答案为他们左右儿子两两组合的较大值???*/
tree merge(tree x,tree y){
	if(!x.l||!y.l) return max(x,y);
	tree c,d,e,f;
	c.l=x.l,c.r=y.l;
	d.l=x.l,d.r=y.r;
	e.l=x.r,e.r=y.l;
	f.l=x.r,f.l=y.r;
	c.lca=query_lca(c.l,c.r);
	d.lca=query_lca(d.l,d.r);
	e.lca=query_lca(e.l,e.r);
	f.lca=query_lca(f.l,f.r);
	c.val=dept[c.l]+dept[c.r]-2*dept[c.lca];
	d.val=dept[d.l]+dept[d.r]-2*dept[d.lca];
	e.val=dept[e.l]+dept[e.r]-2*dept[e.lca];
	f.val=dept[f.l]+dept[f.r]-2*dept[f.lca];
	return max(max(max(max(max(x,y),c),d),e),f);
}
void pushup(ll now){
	t[now]=merge(t[ls],t[rs]);
}
void build(ll now,ll l,ll r){
	if(l==r){
		t[now].l=ys[to[l]].u;
		t[now].r=ys[to[l]].v;
		t[now].lca=query_lca(t[now].l,t[now].r);
		t[now].val=dept[t[now].l]+dept[t[now].r]-2*dept[t[now].lca];
		return;
	}
	ll mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(now);
}
void update(ll now,ll l,ll r,ll x,ll y,ll z){
	if(l==r){
		t[now].l=y;
		t[now].r=z;
		t[now].lca=query_lca(y,z);
		t[now].val=dept[y]+dept[z]-2*dept[t[now].lca];
		return;
	}
	ll mid=l+r>>1;
	if(x<=mid) update(ls,l,mid,x,y,z);
	else update(rs,mid+1,r,x,y,z);
	pushup(now);
}
tree query(ll now,ll l,ll r,ll x,ll y){
	if(l>=x&&r<=y) return t[now];
	tree ans;
	ll mid=l+r>>1;
	if(x<=mid) ans=merge(ans,query(ls,l,mid,x,y));
	if(y>mid) ans=merge(ans,query(rs,mid+1,r,x,y));
	return ans;
}
ll query_ans(ll u,ll v){
	tree ans;
	while(st[u]!=st[v]){
		if(dept[st[u]]<dept[st[v]]) swap(u,v);
		ans=merge(ans,query(1,1,n,dfn[st[u]],dfn[u]));
		u=f[st[u]];
	}
	if(dept[u]>dept[v]) swap(u,v);
	ans=merge(ans,query(1,1,n,dfn[u],dfn[v]));
	return ans.val;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n>>q;
	for(int i=1;i<n;++i){
		ll a,b;
		cin>>a>>b;
		add(a,b),add(b,a);
	}
	dept[1]=1,dfs1(1,0); dfs2(1,1);
	for(int i=1;i<=n;++i) cin>>ys[i].u>>ys[i].v;
	build(1,1,n);
	for(int i=1;i<=n;++i) cout<<"QWQ: "<<t[i].lca<<'\n'; 
	while(q--){
		ll opt,x,y,z;
		cin>>opt>>x>>y;
		if(opt==1){
			cin>>z;
			update(1,1,n,dfn[x],y,z);
		}
		else cout<<query_ans(x,y)<<'\n';
	}
	return 0;
}

T3

在这里自己看link

T4

诡异dp能 O(n2) 做出来,还有 O(nlogn) 的生成函数做法,都不会。

摆了

标程的生成函数代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 5505
#define M 200005
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
int read(){
	int w=0,h=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')h=-h;ch=getchar();}
	while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
	return w*h;
}
const int mod=998244353,g=3,ig=332748118,B=25000;
namespace Polynomial{
	int pwg[B+1],PWG[B+1],pwig[B+1],PWIG[B+1],inv[M],lg[M],pw[M];
	void add(int&x,int y){(x+=y)>=mod?x-=mod:x;}
	inline void Init(){
		for(int i=pwg[0]=1;i<=B;i++)pwg[i]=pwg[i-1]*g%mod;
		for(int i=PWG[0]=1;i<=B;i++)PWG[i]=PWG[i-1]*pwg[B]%mod;
		for(int i=pwig[0]=1;i<=B;i++)pwig[i]=pwig[i-1]*ig%mod;
		for(int i=PWIG[0]=1;i<=B;i++)PWIG[i]=PWIG[i-1]*pwig[B]%mod;
		for(int i=pw[0]=inv[1]=1;i<M;i++)pw[i]=pw[i-1]*2%mod;
		for(int i=2;i<M;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod,lg[i]=lg[i>>1]+1;
	}
	inline int qpow(int k){
		if(k==0)return 1;
		if(k>0)return PWG[k/B]*pwg[k%B]%mod;
		if(k<0)return PWIG[(-k)/B]*pwig[(-k)%B]%mod;
		return 114514;
	}
	inline int qpow(int b,int k){
		int s=1;
		while(k){
			if(k&1)s=s*b%mod;
			b=b*b%mod;k>>=1;
		}
		return s;
	}
	struct Poly{
#define ite vector<int>::iterator
#define rite vector<int>::reverse_iterator
		vector<int>f;
		Poly(){f=vector<int>(0);}
		Poly(int x=0,int y=0){f=vector<int>(x,y);}
		Poly(vector<int>x=vector<int>(0)){f=x;}
		inline int size(){return f.size();}
		inline int back(){return f.back();}
		inline bool empty(){return f.empty();}
		inline int&operator[](int x){return f[x];}
		inline ite begin(){return f.begin();}
		inline ite end(){return f.end();}
		inline rite rbegin(){return f.rbegin();}
		inline rite rend(){return f.rend();}
		inline void swap(Poly&b){vector<int>tmp=f;f=b.f;b.f=tmp;}
		inline void sort(ite BEGIN,ite END){sort(BEGIN,END);}
		inline void sort(rite BEGIN,rite END){sort(BEGIN,END);}
		inline void reverse(ite BEGIN,ite END){reverse(BEGIN,END);}
		inline void emplace_back(int x){f.emplace_back(x);}
		inline void clear(){f.clear();}
		inline void erase(ite x){f.erase(x);}
		inline void pop_back(){f.pop_back();}
		inline void resize(int x){f.resize(x);}
		inline void resize(int x,int y){f.resize(x,y);}
		inline void shrink_to_fit(){f.shrink_to_fit();}
		inline bool operator==(Poly b){return f==b.f;}
		inline bool operator!=(Poly b){return f!=b.f;}
		inline bool operator<(Poly b){return f<b.f;}
		inline bool operator>(Poly b){return f>b.f;}
		inline bool operator<=(Poly b){return f<=b.f;}
		inline bool operator>=(Poly b){return f>=b.f;}
	};
	inline void Complete(Poly&f,int len){while(f.size()<len)f.emplace_back(0);}
	inline void Init(Poly&f,int len){
		int p=pw[lg[len]];
		while(p<len)p<<=1;
		if(len<p)Complete(f,p);
	}// Complete to 2^x
	inline void Cut(Poly&f,int len){while(f.size()>len)f.pop_back();}// Cut useless bits
	inline void NTT(Poly&f,int t){
		if(f.size()==1)return;
		int n=f.size(),buf=1,G=qpow(t*(mod-1)/n);
		Poly l(n>>1),r(n>>1);
		for(int i=0;i<n>>1;i++)l[i]=f[i<<1],r[i]=f[i<<1|1];
		NTT(l,t);NTT(r,t);
		for(int i=0;i<n>>1;i++,buf=buf*G%mod){
			f[i]=(l[i]+buf*r[i]%mod)%mod;
			f[i+(n>>1)]=(l[i]+mod-buf*r[i]%mod)%mod;
		}
	}// NTT
	inline Poly Convol(Poly a,Poly b){
		int len=a.size()+b.size(),p=pw[lg[len]];
		while(p<len)p<<=1;
		Complete(a,p);NTT(a,1);
		Complete(b,p);NTT(b,1);
		for(int i=0;i<p;i++)a[i]=a[i]*b[i]%mod;
		NTT(a,-1);
		for(int i=0;i<p;i++)a[i]=a[i]*inv[p]%mod;
		while(a.back()==0)a.pop_back();
		return a;
	}// Convolution
	inline Poly Inverse(Poly f){
		Init(f,f.size());
		if(f.size()==1)return Poly(1,qpow(f[0],mod-2));
		int n=f.size(),p=pw[lg[n]];
		Poly hlf(n>>1);
		for(int i=0;i<n>>1;i++)hlf[i]=f[i];
		Poly g=Inverse(hlf);
		while(p<n<<1)p<<=1;
		Complete(f,p);NTT(f,1);
		Complete(g,p);NTT(g,1);
		for(int i=0;i<p;i++)g[i]=(2+mod-f[i]*g[i]%mod)%mod*g[i]%mod;
		NTT(g,-1);
		for(int i=n;i<p;i++)g[i]=0;
		for(int i=0;i<p;i++)g[i]=g[i]*inv[p]%mod;
		return g;
	}// Inverse
	inline Poly operator*(Poly a,Poly b){return Poly(Convol(a.f,b.f));}
}
using namespace Polynomial;// call Init() before use
int n,m,q,T,lim,a[N],A[N][N];
vector<Poly>vec;Poly tmp(2),G(0),F(0);
struct Young{
#define mid ((l+r)>>1)
	int table[325][M],type;
	void Apply(int u,int val){
		table[u][++table[u][0]]=val;
		if(type==0&&u<=T)a[u]++;
		if(type==1&&table[u][0]>T)a[table[u][0]]++;
	}
	void Insert(int u,int val){
		if(u>T)return;
		int l=1,r=table[u][0]+1,res=r;
		while(l<=r)((table[u][mid]>val)^type)?res=mid,r=mid-1:l=mid+1;
		if(res>table[u][0])return Apply(u,val);
		swap(val,table[u][res]);Insert(u+1,val);
	}
}young[2];
Poly Divide(int l,int r){return l==r?vec[l]:(Divide(l,mid)*Divide(mid+1,r));}
int Gauss(int n){
	int res=1,op=1;
	for(int i=1,p=0;i<=n;i++,p=0){
		for(int j=i;j<=n&&!p;j++)if(A[j][i])p=j;
		if(i!=p)swap(A[i],A[p]),op*=-1;
		for(int j=i+1;j<=n;j++)
			for(int k=i,coef=A[j][i]*qpow(A[i][i],mod-2)%mod;k<=n;k++)
				add(A[j][k],mod-A[i][k]*coef%mod);
	}
	for(int i=1;i<=n;i++)(res*=A[i][i])%=mod;
	return(mod+res*op)%mod;
}
signed main(){
	//file("startrek-bonus-2");
	young[0].type=0;young[1].type=1;
	n=read();m=read();q=read();T=sqrt(n);Init();
	for(int i=1,p;i<=n;i++)young[0].Insert(1,p=read()),young[1].Insert(1,p);
	for(int i=1;i<=(n=q);i++)lim=max(lim,a[i]+n);
	for(int i=1;i<=m;i++)tmp[0]=1,tmp[1]=mod-read(),vec.emplace_back(tmp);
	Init(G=Divide(0,m-1),lim+1);F=Inverse(G);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[j]+i>=j)A[i][j]=F[a[j]+i-j];
	printf("%lld\n",Gauss(n));
	return 0;
}

T2调了两小时,烦死了

posted @   和蜀玩  阅读(10)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示