T1 ladice

解题思路

我们把一个物品看做 \(A_i\) 与 \(B_i\) 之间的连边。

那么如果加入这条边之后联通块中有超过两个环或者两个环就是不合法的,也就是合法的状态只能是一个基环树和树的森林这样一个形态。

直接并茶几判断连通性,标记一下当前的联通块中是否有环就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<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=3e5+10;
int n,m,fa[N];
bool vis[N];
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
#undef int
int main()
{
#define int register long long
freopen("ladice.in","r",stdin); freopen("ladice.out","w",stdout);
m=read(); n=read();
for(int i=1;i<=n;i++) fa[i]=i;
while(m--)
{
int x,y; x=find(read()); y=find(read());
if(x==y&&vis[x]){printf("SMECE\n");continue;}
if(x!=y&&vis[x]&&vis[y]){printf("SMECE\n");continue;}
if(x==y) vis[x]=true;
else fa[x]=y,vis[y]|=vis[x];
printf("LADICA\n");
}
return 0;
}

T2 card

解题思路

主要是 DP 方程的含义比较难想,\(f_{i,j,k,0/1}\) 表示当前栈中自栈顶到栈底前三个标号是 \(i,j,k\) 。

并且当前可以是否可以选择第一个或者第三个,对于一种已经确定的状态而言,设栈的前三个元素是 \(x,y,z\) ,那么\(z\) 前面的所有牌除了 \(x,y\) 以外一定都已经被取走了,直接前缀和计算即可。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<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=510,INF=1e18;
int n,ans,pre[N];
bool f[N][N][N][2];
struct Node{int a,b,val;}s[N];
bool judge(int x,int y){return s[x].a==s[y].a||s[x].b==s[y].b;}
#undef int
int main()
{
#define int register long long
freopen("card.in","r",stdin); freopen("card.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
s[i].a=read(),s[i].b=read(),
s[i].val=read(),pre[i]=pre[i-1]+s[i].val;
f[1][2][3][0]=true; f[1][2][3][1]=true;
f[2][3][4][0]=judge(1,2); f[1][2][4][1]=judge(3,4);
f[1][2][4][0]=judge(1,3); f[2][3][4][1]=judge(1,4);
for(int i=1;i<=n+5;i++)
for(int j=i+1;j<=n+5;j++)
for(int k=j+1;k<=n+5;k++)
{
if(f[i][j][k][0])
{
f[j][k][k+1][0]|=judge(i,j);
f[j][k][k+1][1]|=judge(i,k+1);
ans=max(ans,pre[min(k-1,n)]-s[j].val);
}
if(f[i][j][k][1])
{
f[i][j][k+1][0]|=judge(k,i);
f[i][j][k+1][1]|=judge(k,k+1);
ans=max(ans,pre[min(k,n)]-s[i].val-s[j].val);
}
}
printf("%lld",ans);
return 0;
}

T3 dojave

解题思路

假设当前选中子串的 \(xor\) 和为 \(Sum\) ,设 \(t=2^M-1\) ,\(d=t\otimes Sum\),我们称 \((x,y)\) 配对当且仅当 \(x\otimes y=Sum\otimes t\) 。

先放一下结论:

不合法的序列一定是长度为 4 的倍数并且序列中的元素可以两两进行配对。

首先序列中元素如果不是两两配对的这个序列一定是合法的。

奇数的情况一定合法,因为至少会存在一个在序列中的 \(x\) 在序列外有一个 \(y\) 与之配对。

对于偶数序列元素两两配对的的情况只有 长度为 4 的倍数才是不合法的。

我们以长度为 6 的为例,那么 \(Sum=d\otimes d \otimes d\) 但是显然 \(d\neq Sum\) ,于是这种情况不存在,其他二的倍数可以类推。

然后代码实现的话可以整一个异或前缀和+桶判断,也可以给两个异或为 \(t\) 的附上两个绝对值相同但是符号不同的数做一遍无序 Hash 。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<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;
}
mt19937 rnd(1ull*time(0)*clock()*rnd()*rand());
const int N=(1<<20)+10;
const ull base=13331; ull t;
int n,m,ans,s[N],pre[N][2],pos[N];
unordered_map<ull,int> cnt[4];
ull id(int x,int y){return 1ull*x*base+y;}
#undef int
int main()
{
#define int long long
freopen("dojave.in","r",stdin); freopen("dojave.out","w",stdout);
m=read(); n=1<<m; ans=n*(n+1)/2;
if(m==1) printf("2"),exit(0); cnt[0].insert(make_pair(0,1));
for(int i=1;i<=n;i++) s[i]=read(),pos[s[i]]=i;
for(int k=0;k<=1;k++) for(int i=1;i<=n;i++) pre[i][k]=pre[pos[(n-1)^s[i]]][k]=rnd()|(rnd()<<15);
for(int k=0;k<=1;k++) for(int i=1;i<=n;i++) pre[i][k]^=pre[i-1][k];
for(int i=1;i<=n;i++) cnt[i%4].insert(make_pair(id(pre[i][0],pre[i][1]),0));
for(int i=1;i<=n;i++) t=id(pre[i][0],pre[i][1]),ans-=cnt[i%4].find(t)->second,cnt[i%4][t]++;
printf("%lld",ans);
return 0;
}

T4 drop

解题思路

求水不是特别好求,我们考虑求出 水+柱子 的体积最后再减去柱子的体积。

发现对于最高的柱子在中间的情况其实可以把最高柱子一侧的柱子平移到另一边,其实是一样的,类似于下图的这种情况:

由于我们计算的是 水+柱子 的体积,因此对于一个位置 \(pos\) 它有意义当且仅当它比他左边或者右边的柱子高。

同时根据上图,我们可以发现其实所有柱子和水的体积之和就是两个次高柱子的高度。

那么我们可以先将所有的柱子从小到大枚举,每次插入一个次小值,然后枚举插入这个柱子后可以构成几个 水+柱子 的体积是这样高度的格子。

一个类似于背包的东西直接 bitset 维护。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<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=5e2+10,M=25e3+10;
int n,cnt,sum,s[N];
bitset<M> bit[N],ans;
#undef int
int main()
{
#define int long long
freopen("drop.in","r",stdin); freopen("drop.out","w",stdout);
n=read(); for(int i=1;i<=n;i++) s[i]=read(),sum+=s[i]; ans[sum]=true;
sort(s+1,s+n+1,greater<int>()); bit[1][s[1]]=true;
for(int i=2;i<=n;i++) bit[i]|=bit[i-1]<<s[2];
for(int i=3;i<=n;i++) if(s[i]!=s[i-1])
{for(int j=i;j<=n;j++) bit[j]|=bit[j-1]<<s[i];ans|=bit[n];}
for(int i=sum;i<=M-10;i++) if(ans[i]) printf("%lld ",i-sum);
return 0;
}

NOIP模拟101(多校33)的更多相关文章

  1. NOIP模拟83(多校16)

    前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...

  2. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  3. NOIP模拟84(多校17)

    T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...

  4. NOIP模拟85(多校18)

    前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...

  5. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

  6. NOIP模拟88(多校21)

    前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...

  7. NOIP模拟96(多校29)

    T1 子集和 解题思路 大概是一个退背包的大白板,然而我考场上想复杂了,竟然还用到了组合数. 但是大概意思是一样的,有数的最小值一定是一个在 \(a\) 数组中存在的数字. 那么我们想办法除去它对应的 ...

  8. NOIP模拟99(多校31)

    T1 法阵 解题思路 原题3100,张口放 T1(出题人原话) 思维题,合法的情况其实就是上下两个梯形拼起来的样子. 他们的边界都是在 \(i\) 轴上面,但是不能相交. 于是我们可以尝试两者相交的纵 ...

  9. noip模拟33[进阶啦啦啦]

    noip模拟33 solutions 不知道该咋说,这场考试其实是我这三四场以来最最最最最顺心的一场了 为啥呢?因为我这回思考有很多结果,得到了脑袋的回复 就是你想了半个小时就有了一点点头绪,那感觉就 ...

  10. noip模拟33

    \(\color{white}{\mathbb{失足而坠千里,翻覆而没百足,名之以:深渊}}\) 这场考试的时间分配非常不科学 开题试图想 \(t1\) 正解,一个半小时后还是只有暴力,特别惊慌失措 ...

随机推荐

  1. Git中 fork, clone,branch

    一.是什么 fork fork,英语翻译过来就是叉子,动词形式则是分叉,如下图,从左到右,一条直线变成多条直线 转到git仓库中,fork则可以代表分叉.克隆 出一个(仓库的)新拷贝 包含了原来的仓库 ...

  2. .netcore 使用Quartz定时任务

    这是一个使用 .NET Core 和 Quartz.NET 实现定时任务的完整示例.首先确保已经安装了 .NET Core SDK.接下来按照以下步骤创建一个新的控制台应用程序并设置定时任务: 创建一 ...

  3. 力扣448(java)-找到数组中所有消失的数(简单)

    题目: 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内.请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果. 示例 ...

  4. 力扣263(java)-丑数(简单)

    题目: 丑数 就是只包含质因数 2.3 和 5 的正整数. 给你一个整数 n ,请你判断 n 是否为 丑数 .如果是,返回 true :否则,返回 false . 示例 1: 输入:n = 6输出:t ...

  5. Hologres如何支持亿级用户UV计算

    简介: 本文将介绍阿里云Hologres如何基于RoaringBitmap进行UV等高复杂度计算的方案,实现亿级用户万级标签亚秒级分析,帮助用户从Kylin平滑迁移到Hologres,实现更实时.开发 ...

  6. 如何用Netty写一个高性能的分布式服务框架?

    简介: Netty 是一个致力于创建高性能网络应用程序的成熟的 IO 框架.相比较与直接使用底层的 Java IO API,不需要先成为网络专家就可以基于 Netty 去构建复杂的网络应用.业界常见的 ...

  7. 无处不在的 Kubernetes,难用的问题解决了吗?

    ​简介: 从第三方的调研数据看,容器和 Kubernetes 已经成为云原生时代主流的选择,但实际落地的时候,却陷入了困境.我们尝试去总结了一些共通点,以及应对方案,也许能为正在落地容器技术的企业提供 ...

  8. GRPC: 如何优雅关闭进程(graceful shutdown)

    ​简介: 本文将介绍优雅关闭 gRPC 微服务.在进程收到关闭信号时,我们需要关闭后台运行的逻辑,比如,MySQL 连接等等. 介绍 本文将介绍优雅关闭 gRPC 微服务. 什么是优雅关闭? 在进程收 ...

  9. dotnet 将控制台 Console.WriteLine 内容输出到文件

    很多伙伴喜欢使用 Console.WriteLine 打日志,也许是打起来顺手.打完了之后,又想着,要是能够输出到本机文件那就更好了.既然很多伙伴都有这个想法,那 dotnet 自然就是有方便的方法让 ...

  10. 用 C# 写脚本 如何输出文件夹内所有文件名

    大部分在 Windows 下的脚本都是使用 bat 或 cmd 写的,这部分的脚本对我来说可读性不好.这个可读性也是很主观的,对我来说用 C# 写脚本的可读性很强,但是换个小伙伴就不是了.在 .NET ...