【CSP-S 2019模拟】题解

T1:

考虑当前位于(x,y)(x,y)
如果走xx,期望多的贡献是(x1)2+(x+1)2/2=1(x-1)^2+(x+1)^2/2=1
所以ans=nans=n

找不到代码了

T2:

考虑实际上就是两棵树两条边分别在另一棵树上包含另一条边
把第二棵树的边在第一棵树上差分后再在第二棵树上单点加链求和
差分一下子树加单点查

O(nlogn)O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define re register
#define pii pair<int,int>
#define fi first
#define se second
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,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;
}
cs int N=1000005;
char xxx;
vector<int> e2[N];
vector<pii> e1[N];
int n;
namespace bit{
	int tr[N];
	#define lb(x) (x&(-x))
	inline void upd(int p,int k){
		for(;p<=n;p+=lb(p))tr[p]+=k;
	}
	inline void update(int l,int r,int k){
		upd(l,k),upd(r+1,-k);
	}
	inline int query(int p){
		int res=0;
		for(;p;p-=lb(p))res+=tr[p];
		return res;
	}
	#undef lb
}
using bit::update;
using bit::query;
int top[N],siz[N],son[N],fa[N],dep[N],in[N],out[N],idx[N],dfn;
int up[N],ans[N];
struct EEE{
	int u,v,lca;
}E2[N];
vector<int> p[N],del[N];
void dfs1(int u){
	siz[u]=1,son[u]=0;
	for(int i=0;i<e1[u].size();i++){
		int v=e1[u][i].fi;
		if(v==fa[u])continue;
		fa[v]=u,dep[v]=dep[u]+1;
		up[v]=e1[u][i].se;
		dfs1(v),siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}
void dfs2(int u,int tp){
	top[u]=tp,in[u]=++dfn;
	if(son[u])dfs2(son[u],tp);
	for(int i=0;i<e1[u].size();i++){
		int v=e1[u][i].fi;
		if(v==fa[u]||v==son[u])continue;
		dfs2(v,v);
	}
	out[u]=dfn;
}
void dfs3(int u){
	siz[u]=1,son[u]=0;
	for(int i=0;i<e2[u].size();i++){
		int v=e2[u][i];
		if(v==fa[u])continue;
		fa[v]=u,dep[v]=dep[u]+1;
		dfs3(v),siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}
void dfs4(int u,int tp){
	top[u]=tp,in[u]=++dfn;;
	if(son[u])dfs4(son[u],tp);
	for(int i=0;i<e2[u].size();i++){
		int v=e2[u][i];
		if(v==fa[u]||v==son[u])continue;
		dfs4(v,v);
	}
	out[u]=dfn;
}
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]?v:u;
}
inline int ask(int u,int v){
	return query(in[u])+query(in[v])-2*query(in[Lca(u,v)]);
}
void dfs5(int u,int f){
	int pre=0;
	if(u>1)pre=ask(u,f);
	for(int i=0;i<e1[u].size();i++){
		int v=e1[u][i].fi;
		if(v==f)continue;
		dfs5(v,u);
	}
	for(int i=0;i<p[u].size();i++){
		int x=p[u][i];
		update(in[x],out[x],1);
	}
	for(int i=0;i<del[u].size();i++){
		int x=del[u][i];
		update(in[x],out[x],-2);
	}
	ans[up[u]]=ask(u,f)-pre;
}
char yyy;
int main(){
int size=40<<20;//40M
    //__asm__ ("movl  %0, %%esp\n"::"r"((char*)malloc(size)+size));//调试用这个 
    __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//提交用这个 

    //main函数代码 
	n=read();
	for(re int i=1;i<n;i++){
		int u=read(),v=read();
		e1[u].pb(pii(v,i)),e1[v].pb(pii(u,i));
	}
	for(re int i=1,u,v;i<n;i++){
		u=read(),v=read();
		e2[u].pb(v),e2[v].pb(u);
		E2[i].u=u,E2[i].v=v;
	}
	dfs1(1),dfs2(1,1);
	for(re int i=1;i<n;i++)E2[i].lca=Lca(E2[i].u,E2[i].v);
	dfn=0,dfs3(1);
	dfs4(1,1);
	for(re int i=1,u,v,lca;i<n;i++){
		u=E2[i].u,v=E2[i].v,lca=E2[i].lca;
		if(dep[u]<dep[v])swap(u,v);
		p[u].pb(u),p[v].pb(u),del[lca].pb(u);
	}
	dfs5(1,0);
	for(int i=1;i<n;i++)cout<<ans[i]<<" ";
	exit(0);
}

T3:

DAGDAG上类似重剖,找方案最多的儿子,预处理向下的倍增数组
这样每次跳必然方案数减半

O(nlog2n)O(nlog^2n)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define re register
#define pii pair<int,int>
#define fi first
#define se second
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,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;
}
int n,m;
cs int N=200005;
int down[N][21],cost[N][21];
vector<int> e[N],val[N],ss[N];
int f[N],son[N],in[N],rt;
cs int lim=1e9+2;
inline int add(int a,int b){
	return min(lim,a+b);
}
void dfs(int u){
	if(f[u])return;
	int hv=0;
	for(int &v:e[u]){
		dfs(v);
		if(f[v]>f[son[u]])son[u]=v,hv=f[u]+1;
		f[u]=add(f[u],f[v]+1);
		val[u].pb(f[u]);
	}
	down[u][0]=son[u],cost[u][0]=hv;
	for(int i=1;i<19;i++)down[u][i]=down[down[u][i-1]][i-1],cost[u][i]=add(cost[u][i-1],cost[down[u][i-1]][i-1]);
}
int find(int u,int k){
	if(!k)return u;
	for(int i=18;~i;i--){
		if(down[u][i]&&cost[u][i]<=k&&k<=cost[u][i]+f[down[u][i]])
		return find(down[u][i],k-cost[u][i]);
	}
	int pos=lower_bound(val[u].bg(),val[u].end(),k)-val[u].bg();
	if(!pos)return find(e[u][pos],k-1);
	return find(e[u][pos],k-val[u][pos-1]-1);
}
int main(){
	#ifdef Stargazer
	freopen("lx.cpp","r",stdin);
//	freopen("my.out","w",stdout);
	#endif
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		e[u].pb(v),in[v]++;
	}
	for(int i=1;i<=n;i++)if(!in[i])rt=i;
	dfs(rt);
	int q=read();
	while(q--){
		int u=read(),k=read();
		if(k>f[u]){cout<<-1<<'\n';}
		else cout<<find(u,k)<<'\n';
	}
}
posted @ 2019-10-27 13:14  Stargazer_cykoi  阅读(117)  评论(0编辑  收藏  举报