模拟71 考试总结

日常签到失败

T1.签到题

所以现在的签到题都写着签到题了吗
结论题,考场没看出来,就死了,成功签到失败
下界是所有点如果连边为\(c\)的倍数则贡献为0,否则为1,答案确实是这个下界
证明需要用到二分图维津定理,扔链接就跑

#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{		
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const int N=1000050;
int n,m,k,c,du1[N],du2[N];
signed main()
{
	freopen("qiandao.in","r",stdin);
	freopen("qiandao.out","w",stdout);
	n=read(),m=read(),k=read(),c=read();
	for(int i=1;i<=k;i++)
	{
		int x=read(),y=read();
		du1[x]++;du2[y]++;
	}
	int ans=0;
	for(int i=1;i<=n;i++)if(du1[i]%c)ans++;
	for(int i=1;i<=m;i++)if(du2[i]%c)ans++;
	cout<<ans<<endl;
	return 0;
}

那么教训就是盲猜结论也是做题的一部分

T2.M弟娃

这才是签到题吧……
都是套路,dfs序线段树维护每个点的答案,每次考虑两个点的位置,若两点相同则全局答案加1,若lca不与任意一点相同则二者子树答案加1,否则整棵树除了这条链都加1,直接维护即可,边界稍微留意

#include <bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const int N=300050;
struct node{
	int from,to,next;
}a[2*N];
int head[N],mm=1;
inline void add(int x,int y)
{
	a[mm].from=x;a[mm].to=y;
	a[mm].next=head[x];head[x]=mm++;
}
struct tree{
	int ma,lazy;
}tr[4*N];	
inline void luo(int id,int l,int r)
{
	if(tr[id].lazy&&l!=r)
	{	
		tr[id*2].lazy+=tr[id].lazy;
		tr[id*2+1].lazy+=tr[id].lazy;
		tr[id*2].ma+=tr[id].lazy;
		tr[id*2+1].ma+=tr[id].lazy;
		tr[id].lazy=0;
	}	
}	
void change(int id,int pl,int pr,int l,int r,int v)
{
	if(l>r)return;
	if(l<=pl&&r>=pr)
	{
		tr[id].lazy+=v;
		tr[id].ma+=v;return;
	}
	luo(id,pl,pr);int mid=(pl+pr)>>1;
	if(r<=mid)change(id*2,pl,mid,l,r,v);
	else if(l>mid)change(id*2+1,mid+1,pr,l,r,v);
	else change(id*2,pl,mid,l,mid,v),change(id*2+1,mid+1,pr,mid+1,r,v);
	tr[id].ma=max(tr[id*2].ma,tr[id*2+1].ma);
}
int d[N],sum,id[N],tot,t;
int f[N][20],size[N];bool v[N];
void dfs(int x)
{
	v[x]=1;id[x]=++tot;
	for(int i=head[x];i;i=a[i].next)
	{
		int y=a[i].to;
		if(v[y])continue;
		d[y]=d[x]+1;f[y][0]=x;
		for(int j=1;j<=t;j++)
		 f[y][j]=f[f[y][j-1]][j-1];
		dfs(y);size[x]+=size[y];
	}
	size[x]++;
}
inline int getlca(int x,int y)
{
	if(d[x]<d[y])swap(x,y);
	for(int i=t;i>=0;i--)
	{
		if(d[f[x][i]]<d[y])continue;
		x=f[x][i];
	}
	if(x==y)return x;
	for(int i=t;i>=0;i--)
	{
		if(f[x][i]==f[y][i])continue;
		x=f[x][i],y=f[y][i];
	}	
	return f[x][0];
}
inline void gan(int &x,int y)
{
	for(int i=t;i>=0;i--)
	{
		if(d[f[x][i]]<=d[y])continue;
		x=f[x][i];
	}
}
signed main()
{	
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	int n,m;cin>>n>>m;t=log2(n)+1;
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		add(x,y);add(y,x);
	}
	d[1]=1;dfs(1);
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		if(x==y)sum++;
		else
		{	
			int lca=getlca(x,y);
			if(lca==x||lca==y)
			{
				if(d[x]<d[y])swap(x,y);
				change(1,1,n,id[x],id[x]+size[x]-1,1);gan(x,y);
				change(1,1,n,id[x],id[x]+size[x]-1,-1);sum++;
			}
			else
			{
				change(1,1,n,id[x],id[x]+size[x]-1,1);
				change(1,1,n,id[y],id[y]+size[y]-1,1);
			}
		}
		printf("%d\n",tr[1].ma+sum);
	}
	return 0;
}

某oj较为卡常,要手动开O2

T3.变异大老鼠

发现每个点只有一个前驱,所以可以跑最短路记前驱然后建一棵树
然后就是树形dp了,写的子树合并

#include <bits/stdc++.h>
using namespace std;
const int N=310,M=50050;
const int exs=1e-9;
struct node{
	int from,to,next,w;
}a[2*M];
int head[N],mm=1;
inline void add(int x,int y,int z)
{	
	a[mm].from=x;a[mm].to=y;a[mm].w=z;
	a[mm].next=head[x];head[x]=mm++;
}
int dis[N],n,m,k,fr[N];
double p[N][N],f[N][N],g[N];bool v[N];
inline void dij()
{
	priority_queue <pair<int,int> >q;
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;fr[1]=1;q.push(make_pair(0,1));
	while(q.size())
	{
		int x=q.top().second,w=-q.top().first;q.pop();
		if(v[x])continue;v[x]=1;
		for(int i=head[x];i;i=a[i].next)
		{
			int y=a[i].to;
			if(y==x)continue;
			if(dis[x]+a[i].w<dis[y])
			 dis[y]=dis[x]+a[i].w,q.push(make_pair(-dis[y],y)),fr[y]=x;
		}
	}
}
inline double gan(double x,int y)
{
	if(!y)return 0.0;
	return x/(double)y;
}
void dfs(int x)
{
	int size=0;memset(g,0,sizeof(g));
	for(int i=head[x];i;i=a[i].next)
	{
		int y=a[i].to;dfs(y);
		memset(g,0,sizeof(g));
		for(int j=0;j<=k;j++)
		 for(int p=0;p<=j;p++)
		  g[j]=max(g[j],gan(f[y][p],size+1)+gan(f[x][j-p]*size,size+1));
		for(int j=0;j<=k;j++)f[x][j]=g[j];
		size++;
	}
	memset(g,0,sizeof(g));
	for(int i=0;i<=k;i++)
	 for(int j=0;j<=i;j++)
	  g[i]=max(f[x][j]*(1-p[x][i-j])+p[x][i-j],g[i]);
	for(int i=0;i<=k;i++)f[x][i]=g[i];
}
signed main()
{
	freopen("arrest.in","r",stdin);
	freopen("arrest.out","w",stdout);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);add(y,x,z);
	}		
	for(int i=1;i<=n;i++)for(int j=1;j<=k;j++)scanf("%lf",&p[i][j]);
	dij();memset(a,0,sizeof(a));memset(head,0,sizeof(head));mm=1;
	for(int i=2;i<=n;i++)add(fr[i],i,0);
	dfs(1);printf("%.6lf",f[1][k]);
	return 0;
}

T4.朝鲜时蔬

由于过于难以一句话描述所以另开一篇
有些受震撼

考试总结

考试技巧还是不太足,不要老想着正解,猜结论打表也很重要
心理能力要足够好,敢于面对一些(看起来)很毒瘤的题面
永远不要有“得xx分就够了的思想”,别人可能AK,不要弃疗

上一篇:最新建筑施工物料提升机(建筑特种作业)机考题库及建筑物料提升机模拟试题


下一篇:vue学习---过滤器Vue.filter / {{ xxx | 过滤器名}}