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.. 其实是一道欧拉路的题,把每条非自环的边看 ...
随机推荐
- Jedis连接踩坑日记
Jedis连接踩坑日记 背景: 线上某块业务的增删改功能全部都不可用.页面发送了xhr请求之后 状态一直处于pending状态,后端没有日志产生 排查路线与解决办法 第一:由于服务在内网里面,无法进行 ...
- C/C++常考习题
1.什么是虚函数?什么是纯虚函数? 虚函数:允许被其子类重新定义的成员函数. 虚函数的声明:virtual returntype func(parameter);引入虚函数的目的是为了动态绑定: 纯虚 ...
- docker containerd runc containerd-shim等组件的关系
早期 kubelet 创建容器工作原理 因为 docker 出生的比 k8s 早,所以 k8s 早期的容器运行时都是基于 docker 的,kubelet 通过 docker 的 api 创建容器.后 ...
- ping的常用方法
ping的常用方法 ping +ip tcping +ip+端口号(例如 tcping 127.0.0.1 8080) telnet +ip+端口号 nc -nzv +ip+端口号(linux用)
- 力扣618(MySQL)-学生地理信息报告(困难)
题目: 一所美国大学有来自亚洲.欧洲和美洲的学生,他们的地理信息存放在如下 student 表中 该表没有主键.它可能包含重复的行.该表的每一行表示学生的名字和他们来自的大陆. 一所学校有来自亚洲.欧 ...
- 力扣197(MySQL)-上升的温度(简单)
题目: 表: Weather 编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 id . 返回结果 不要求顺序 . 查询结果格式如下例. 解题思路: 方法一:使用窗口函数la ...
- 力扣190(java)-颠倒二进制位(简单)
题目: 颠倒给定的 32 位无符号整数的二进制位. 提示: 请注意,在某些语言(如 Java)中,没有无符号整数类型.在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论 ...
- 【译】Visual Studio Enterprise 中的代码覆盖率特性
通过使用代码覆盖率功能,您可以发现您的测试需要改进的地方,并使您的软件更加健壮和可靠.在这篇文章中,我们将介绍我们在 Visual Studio Enterprise 2022 中引入的 Code C ...
- EasyNLP发布融合语言学和事实知识的中文预训练模型CKBERT
简介: 本⽂简要介绍CKBERT的技术解读,以及如何在EasyNLP框架.HuggingFace Models和阿里云机器学习平台PAI上使⽤CKBERT模型. 导读 预训练语言模型在NLP的各个应用 ...
- dotnetCampus.UITest.WPF 一个支持中文用例的界面单元测试框架
本文来安利大家一个支持使用中文做用例名的 WPF 界面 UI 单元测试框架 卖点 有没有觉得命名太难?有没有觉得单元测试的命名更难?没错,这是一个业界的大问题.很多团队都会因为单元测试的用例函数命名太 ...