8.14考试总结(NOIP模拟39)[打地鼠·竞赛图·糖果·树]
一举一动,都是承诺,会被另一个人看在眼里,记在心上的。
T1 打地鼠
解题思路
数据范围比较小,不需要什么优化。
直接二维前缀和枚举右下角端点就好了。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=2e3+10;
int n,m,ans,s[N][N],pre[N][N];
char ch[N];
signed main()
{
	n=read();	m=read();
	for(int i=1;i<=n;i++)
	{
		scanf("%s",ch+1);
		for(int j=1;j<=n;j++)
			s[i][j]=ch[j]-'0';
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+s[i][j];
	if(m>=n)
	{
		printf("%lld",pre[n][n]);
		return 0;
	}
	for(int i=m;i<=n;i++)
		for(int j=m;j<=n;j++)
			ans=max(ans,pre[i][j]-pre[i-m][j]-pre[i][j-m]+pre[i-m][j-m]);
	printf("%lld",ans);
	return 0;
}
T2 竞赛图
解题思路
设 \(e(S)\) 表示点集 \(S\) 向点集以外的点的连边的交集为 \(e(S)\) 。
我们已经知道了每一个点向外面连边的点集了。
因此可以把大的集合拆成两部分对于两部分的 e 取交集。
这里为了方便直接取了 \(lowbit\) 。。。
因为保证了每两个点之间只有一条有向边,因此 \(S\) 向 \(e(S)\) 的任何一个子集的连边一定是单向的。
因此他们共同构成的一个点集不是强联通的,其他的就是合法的了。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=25;
int T,n,ans,e[1<<N];
bool jud[1<<N];
int lowbit(int x){return x&(-x);}
void solve()
{
	memset(e,0,sizeof(e));
	memset(jud,true,sizeof(jud));
	n=read();	ans=0;
	e[0]=(1<<n)-1;
	for(int i=1;i<=n;i++)
		for(int j=1,x;j<=n;j++)
		{
			x=read();
			e[1<<i-1]|=x<<j-1;
		}
	for(int i=1;i<(1<<n);i++)
		e[i]=e[i^lowbit(i)]&e[lowbit(i)];
	for(int i=1;i<(1<<n);i++)
		if(jud[i])
			for(int j=e[i];j;j=(j-1)&e[i])
				jud[i|j]=false;
	for(int i=0;i<(1<<n);i++)
		ans+=jud[i];
	printf("%lld\n",ans);
}
signed main()
{
	T=read();
	while(T--)	solve();
	return 0;
}
T3 糖果
解题思路
动态规划
设 \(f_{i,j,k}\) 表示当前小A选择到 i ,小B选择到 j ,小C还有 k 个备选位置。
如果 i 当前扫到的数在 a 中的优先级比 b 小,那么就一定是被小C 拿走了,先加到以后的里面去。
否则的话就相当于是小A选走了,那么此时的小C的备选位置就少了一个。
然后对于小B 的选择也是类似。
为了方便转移,我们再给 f 数组加一维\(0/1\) 表示当前进行到了那一步。
由于我太菜了,至今都没想到问什么后面要乘上一个 \(3\times i-1\)和 \(3\times i -2\)。(逃
upd on 8.19:由于我们之前求出来的其实是小 C 每一轮选择的方案数。
那么对于第 i 轮而言,在小 C 选之前小 A 和小 B 一定各选了一个数,并且一定是在小 C 当前要选的数的优先级之前选的。
举个例子就是 i=3 的时候此时小 C 应该选择第 9 个数,那么小 A 和小 B 选择的就是小 C 整个喜好序列中的前 8 个数。
方案就有 \(A_8^2\) 因此对于第 i 轮而言要乘上一个 \(A_i^i\)。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=410,M=150,mod=1e9+7;
int n,ans,f[N][N][M][2],a[N],b[N],pos1[N],pos2[N];
signed main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		pos1[a[i]]=i;
	}
	for(int i=1;i<=n;i++)
	{
		b[i]=read();
		pos2[b[i]]=i;
	}
	f[1][1][0][0]=1;
	for(int i=1;i<=n+1;i++)
		for(int j=1;j<=n+1;j++)
			for(int k=0;k<=n/3;k++)
			{
				if(f[i][j][k][0])
				{
					if(i==n+1)
					{
						if(!k)	ans=(ans+f[i][j][k][0])%mod;
						continue;
					}
					if(pos2[a[i]]<j)	(f[i+1][j][k][0]+=f[i][j][k][0])%=mod;
					else
					{
						(f[i][j][k][1]+=f[i][j][k][0])%=mod;
						if(k)	(f[i+1][j][k-1][0]+=f[i][j][k][0]*k%mod)%=mod;
					}
				}
				if(f[i][j][k][1])
				{
					if(pos1[b[j]]<i)	(f[i][j+1][k][1]+=f[i][j][k][1])%=mod;
					else	if(a[i]!=b[j])
					{
						(f[i+1][j+1][k+1][0]+=f[i][j][k][1])%=mod;
						if(k)	(f[i][j+1][k-1][1]+=f[i][j][k][1]*k%mod)%=mod;
					}
				}
			}
	for(int i=1;i<=n;i++)
		if(i%3)
			ans=ans*i%mod;
	printf("%lld",ans);
	return 0;
}
T4 树
解题思路
几乎是今年 NOI 的原题吧(尽管我没有资格去考,也没有看过这个题)
在每一次操作的时候给每一个点涂上一种新的颜色。
那么两端颜色相同的就是白色边,反之就是黑色边。
然后就可以直接树链剖分+线段树维护当前区间的颜色种类数以及两端的颜色了。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=3e5+10;
int n,q,col;
int tot,head[N],ver[N<<1],nxt[N<<1];
int tim,dep[N],siz[N],son[N],topp[N],fa[N],dfn[N],id[N];
struct Segment_Tree
{
	int dat,laz,lc,rc;
}tre[N<<2];
void add_edge(int x,int y)
{
	ver[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void dfs1(int x)
{
	siz[x]=1;
	for(int i=head[x];i;i=nxt[i])
	{
		int to=ver[i];
		if(siz[to])	continue;
		dep[to]=dep[x]+1;
		fa[to]=x;
		dfs1(to);
		siz[x]+=siz[to];
		if(siz[to]>siz[son[x]])
			son[x]=to;
	}
}
void dfs2(int x,int tp)
{
	dfn[x]=++tim;
	id[tim]=x;
	topp[x]=tp;
	if(son[x])	dfs2(son[x],tp);
	for(int i=head[x];i;i=nxt[i])
		if(!dfn[ver[i]])
			dfs2(ver[i],ver[i]);
}
void push_up(int x)
{
	tre[x].dat=tre[ls].dat+tre[rs].dat+(tre[ls].rc!=tre[rs].lc);
	tre[x].lc=tre[ls].lc;	tre[x].rc=tre[rs].rc;
}
void push_down(int x)
{
	if(!tre[x].laz)	return ;
	tre[ls].dat=tre[rs].dat=0;
	tre[ls].lc=tre[rs].lc=tre[ls].rc=tre[rs].rc=tre[x].laz;
	tre[ls].laz=tre[rs].laz=tre[x].laz;
	tre[x].laz=0;
}
void build(int x,int l,int r)
{
	if(l==r)
	{
		tre[x].lc=tre[x].rc=++col;
		tre[x].dat=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	push_up(x);
}
int query(int x,int l,int r,int pos)
{
	if(l==r)	return tre[x].lc;
	push_down(x);
	int mid=(l+r)>>1,ans;
	if(pos<=mid)	ans=query(ls,l,mid,pos);
	else	ans=query(rs,mid+1,r,pos);
	push_up(x);
	return ans;
}
int query(int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)	return tre[x].dat;
	push_down(x);
	int mid=(l+r)>>1,sum=0;
	if(L<=mid)	sum+=query(ls,l,mid,L,R);
	if(R>mid)	sum+=query(rs,mid+1,r,L,R);
	sum+=(L<=mid&&R>mid&&tre[ls].rc!=tre[rs].lc);
	push_up(x);
	return sum;
}
void update(int x,int l,int r,int L,int R,int num)
{
	if(L<=l&&r<=R)
	{
		tre[x].dat=0;
		tre[x].lc=tre[x].rc=num;
		tre[x].laz=num;
		return ;
	}
	push_down(x);
	int mid=(l+r)>>1;
	if(L<=mid)	update(ls,l,mid,L,R,num);
	if(R>mid)	update(rs,mid+1,r,L,R,num);
	push_up(x);
}
void update(int x,int y)
{
	col++;
	while(topp[x]^topp[y])
	{
		if(dep[topp[x]]<dep[topp[y]])
			swap(x,y);
		update(1,1,tim,dfn[topp[x]],dfn[x],col);
		x=fa[topp[x]];
	}
	if(dep[x]>dep[y])	swap(x,y);
	update(1,1,tim,dfn[x],dfn[y],col);
}
int solve(int x,int y)
{
	int sum=0;
	while(topp[x]^topp[y])
	{
		if(dep[topp[x]]<dep[topp[y]])
			swap(x,y);
		sum+=query(1,1,tim,dfn[topp[x]],dfn[x]);
		sum+=(query(1,1,tim,dfn[topp[x]])!=query(1,1,tim,dfn[fa[topp[x]]]));
		x=fa[topp[x]];
	}
	if(dep[x]>dep[y])	swap(x,y);
	sum+=query(1,1,tim,dfn[x],dfn[y]);
	return sum;
}
signed main()
{
	n=read();
	for(int i=1,x,y;i<n;i++)
	{
		x=read();	y=read();
		add_edge(x,y);
		add_edge(y,x);
	}
	dfs1(1);
	dfs2(1,1);
	build(1,1,tim);
	q=read();
	while(q--)
	{
		int opt,x,y;
		opt=read();	x=read();	y=read();
		if(opt==1)	update(x,y);
		else	if(x!=y)	printf("%lld\n",solve(x,y));
		else	printf("0\n");
	}
	return 0;
}
												
											8.14考试总结(NOIP模拟39)[打地鼠·竞赛图·糖果·树]的更多相关文章
- 2021.8.14考试总结[NOIP模拟39]
		
T1 打地鼠 全场就俩人没切,还有一个是忘关$freopen$了. $code:$ 1 #include<bits/stdc++.h> 2 #define rin register sig ...
 - 2021.9.14考试总结[NOIP模拟53]
		
T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...
 - [考试总结]noip模拟39
		
不写那么多没用的了 开题就发现 \(T4\) 原题, \(T1\) 大水题. 然后发现 \(T4\) 忘了.... 不扯了 打地鼠 大水题,我代码都不想放... 算了,还是放一下吧.. #includ ...
 - 8.23考试总结(NOIP模拟46)[数数·数树·鼠树·ckw的树]
		
T1 数数 解题思路 大概是一个签到题的感觉...(但是 pyt 并没有签上) 第一题当然可以找规律,但是咱们还是老老实实搞正解吧... 先从小到大拍个序,这样可以保证 \(a_l<a_r\) ...
 - 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]
		
6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...
 - 5.23考试总结(NOIP模拟2)
		
5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...
 - 5.22考试总结(NOIP模拟1)
		
5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...
 - 2021.9.17考试总结[NOIP模拟55]
		
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
 - [考试总结]noip模拟23
		
因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...
 - 2021.6.17考试总结[NOIP模拟8]
		
T1 星际旅行 其实就是求两条只走一遍的边的方案数. 考场上第一眼就感觉不可做,后来画了几个图,发现好像只要两个边是相连的就可以只走一遍,居然还真拿了30.. 其实是一道欧拉路的题,把每条非自环的边看 ...
 
随机推荐
- 第四章:if else switch使用
			
/* * @Issue: 输入整数a和b,若a²+b²大于100,则输出a²+b²之和的百位以上的数字,否则直接输出a²+b²的和 * @Author: 一届书生 * @LastEditTime : ...
 - Signalr断线重连机制
			
前言 Signalr 即时消息发布到服务器后发现链接老是自动断开,导致无法发送广播后面百度搜了一下,signalr有个超时的机制 解决办法(js) //链接到自己的hub var connection ...
 - opensips使用drouting进行路由
			
操作系统 :CentOS 7.6_x64 opensips版本:2.4.9 drouting是Dynamic Routing(动态路由)的缩写,该模块可为特定呼叫选择(基于多个条件)最佳网关.今天整理 ...
 - MD5前端vue加密
			
Vue 前端md5加密用户注册时将加密后的密码发送给后端存储当登陆的时候,再将加密后的密码和数据库中加密的密码相匹配.npm: https://www.npmjs.com/package/crypto ...
 - 如何基于MaxCompute快速打通数据仓库和数据湖的湖仓一体实践
			
简介: MaxCompute 是面向分析的企业级 SaaS 模式云数据仓库,以 Serverless 架构提供快速.全托管的在线数据仓库服务,消除了传统数据平台在资源扩展性和弹性方面的限制,最小化用户 ...
 - [Go] Golang并发控制: WaitGroup 含义和常规用法
			
一个 WaitGroup 等待一个 goroutine 集合的结束. 主 goroutine 调用 Add 设置需要等待的 goroutine 数量. 接下来每个 goroutine 运行并在结束时调 ...
 - [Blockchain] Cosmos Starport 安装的三种方式
			
官方二进制包方式: # 下载 starport 二进制到 /usr/local/bin $ curl https://get.starport.network/starport! | bash # ...
 - 为 RabbitMQ 服务器启用 SSL/TLS
			
为 RabbitMQ 服务器启用 SSL/TLS 目录 为 RabbitMQ 服务器启用 SSL/TLS 为客户端和服务器生成自签名证书 在 RabbitMQ 服务器中启用 TLS/SSL 支持 使用 ...
 - docker.from_env() 获取docker守护进程时出现 TypeError: load_config() got an unexpected keyword argument 'config_dict' 异常
			
某天使用python重启docker容器时,出现了一个令人费解的BUG,我的代码为 1 def restart_docker(container_name): 2 # 连接到docker守护进程 3 ...
 - 【web安全】隐藏nginx头文件信息
			
摘要 Nginx作为开源web中间件,被广泛应用.因此源编译或者yum安装,都会带有其原有的nginx版本.很容易被针对,因此,通过修改nginx的源码.隐藏nginx版本和头部信息,保障nginx的 ...