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. Flutter笔记 - 布局类组件

    布局类组件 Row水平方向排列 textDirection 水平方向子组件布局顺序. mainAxisSize 占用空间,默认MainAxisSize.MAX mainAxisAligment 对齐方 ...

  2. 函数模板 及显式具体化(C++)

    函数模板 将同一种算法应用与不同类型的函数时 #include<iostream> #include<string> template <typename T> v ...

  3. 中国大陆地区维护的Linux操作系统

    Linux开源生态丰富,中国大陆地区基于CentOS停服,依托阿里云.腾讯云.华为云三大私营企业,相继发布了自己的开源Linux定制版,很高兴的是他们只是改个名字并没有选择闭门造车,只是官网还是很不耻 ...

  4. 剑指offer56(Java)-数组中出现的次数Ⅰ(中等)

    题目: 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1, ...

  5. 力扣451(java)-根据字符出现频率排序(中等)

    题目: 给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 .一个字符出现的 频率 是它出现在字符串中的次数. 返回 已排序的字符串 .如果有多个答案,返回其中任何一个. 示例 1: 输入 ...

  6. 第 7章 Python 爬虫框架 Scrapy(上)

    第 7章 Python 爬虫框架 Scrapy(上) 编写爬虫可以看成行军打仗,基本的角色有两个:士兵和将军,士兵冲锋陷阵,而将军更多地是调兵遣将.框架就像一个将军,里面包含了爬虫的全部流程.异常处理 ...

  7. 爱奇艺在 Dubbo 生态下的微服务架构实践

    简介: 本文整理自作者于 2020 年云原生微服务大会上的分享<爱奇艺在 Dubbo 生态下的微服务架构实践>,重点介绍了爱奇艺在 Dubbo.Sentinel 等开发框架方面的使用经验以 ...

  8. 来电科技:基于Flink+Hologres的实时数仓演进之路

    简介: 本文将会讲述共享充电宝开创企业来电科技如何基于Flink+Hologres构建统一数据服务加速的实时数仓 作者:陈健新,来电科技数据仓库开发工程师,目前专注于负责来电科技大数据平台离线和实时架 ...

  9. MySQL 深潜 - 一文详解 MySQL Data Dictionary

    ​简介: 在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复 ...

  10. UWP 从文件 StorageFile 转 SoftwareBitmap 图片方法

    本文告诉大家如何在 UWP 从 文件 StorageFile 转 SoftwareBitmap 图片的方法 使用以下三步即可从文件 StorageFile 转 SoftwareBitmap 图片 第一 ...