T1 饥饿的狐狸

解题思路

贪心签到题。

最小值的做法就是对于温度比水小的从大到小吃,然后喝一口水,然后把剩下的从小到大吃掉。

最大值的做法,几乎就是大的挑一个小的挑一个间隔着吃,可以排完序之后双指针扫两边,但是我码了一大堆。。

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=1e5+10;
int n,ans1,ans2,val,las,s[N];
priority_queue<int> q1;
priority_queue<int,vector<int>,greater<int> > q2;
void solve1()
{
for(int i=1;i<=n;i++)
if(s[i]>=val) q1.push(s[i]);
else q2.push(s[i]);
las=val;
while(!q1.empty()&&!q2.empty())
{
int x=q1.top(),y=q2.top(); q1.pop(); q2.pop();
ans1+=x-las+x-y; las=y;
}
if(q1.empty()&&q2.empty()) return ;
if(!q1.empty())
{
multiset<int> res;
ans1+=val-las;
while(!q1.empty()) res.insert(q1.top()),q1.pop();
while(res.size()>=2)
{
int x=*res.begin(),y=*res.rbegin(); if(y-x<=x-val) break;
res.erase(res.find(x)); res.erase(res.find(y));
ans1+=y-val+y-x;
}
while(res.size()) ans1+=(*res.begin())-val,res.erase(res.begin());
return ;
}
multiset<int> res;
while(!q2.empty()) res.insert(q2.top()),q2.pop();
while(res.size()>=2)
{
int x=*res.begin(),y=*res.rbegin(); if(y-x<=val-y) break;
res.erase(res.find(x)); res.erase(res.find(y));
ans1+=val-x+y-x;
}
while(res.size()) ans1+=val-(*res.begin()),res.erase(res.begin());
}
void solve2()
{
for(int i=1;i<=n;i++)
if(s[i]>=val) q1.push(s[i]);
else q2.push(s[i]);
las=val;
while(!q1.empty()&&!q2.empty())
{
int x=q1.top(),y=q2.top(); q1.pop(); q2.pop();
ans2+=las-y+x-y; las=x;
}
if(q1.empty()&&q2.empty()) return ;
if(!q1.empty())
{
multiset<int> res;
while(!q1.empty()) res.insert(q1.top()),q1.pop();
while(res.size()>=2)
{
int x=*res.begin(),y=*res.rbegin(); if(y-x<=x-val) break;
res.erase(res.find(x)); res.erase(res.find(y));
ans2+=y-val+y-x;
}
while(res.size()) ans2+=(*res.begin())-val,res.erase(res.begin());
return ;
}
multiset<int> res;
ans2+=las-val;
while(!q2.empty()) res.insert(q2.top()),q2.pop();
while(res.size()>=2)
{
int x=*res.begin(),y=*res.rbegin(); if(y-x<=val-y) break;
res.erase(res.find(x)); res.erase(res.find(y));
ans2+=val-x+y-x;
}
while(res.size()) ans2+=val-(*res.begin()),res.erase(res.begin());
}
#undef int
int main()
{
#define int long long
freopen("a.in","r",stdin); freopen("a.out","w",stdout);
n=read(); las=val=read();
for(int i=1;i<=n;i++) s[i]=read();
for(int i=1;i<=n;i++)
if(s[i]<val) q1.push(s[i]);
else if(s[i]>val) q2.push(s[i]);
while(!q1.empty()) ans1+=las-q1.top(),las=q1.top(),q1.pop();
las=val; while(!q2.empty()) ans1+=q2.top()-las,las=q2.top(),q2.pop();
printf("%lld ",ans1); ans1=0; solve1(); solve2();
printf("%lld",max(ans1,ans2));
return 0;
}

T2 保险箱

解题思路

假设密码数组是 \(c\)。

那么就要满足 \(c\) 数组的所有值以及 \(n\) 配上任意的系数相加之后都不可以等于 \(1\sim K-1\) 中的任何一个 \(m_i\)

那么根据裴蜀定理可以得到\(\gcd(n,c_1,c_2...)\nmid m_i\) 。

那么一个比较暴力的做法就出来了:枚举 \(\gcd(n,m_K)\) 的每一个因数判断是否合法,然后选取最大的。

考虑优化一下,对于任何一个 \(m_i\) 而言,它的任何一个因子都是不可以的,那么它在 \(\gcd(n,m_K)\) 的因子这个范围中的因子一定是 \(\gcd(m_i,\gcd(n,m_K))\) 的因数。

于是我们可以先算出来 \(\gcd(n,m_K)\) 的每一个质因子,然后对于每一个 \(\gcd(m_i,\gcd(n,m_K))\) 记忆话搜索就好了。

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=25e4;
int n,g,temp,m,mx,s[N];
vector<int> pri;
set<int> res,in;
inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
bool check(int x){return res.find(x)==res.end();}
void dfs(int x){if(!check(x))return ;res.insert(x);for(auto y:pri)if(x%y==0)dfs(x/y);}
#undef int
int main()
{
#define int register long long
freopen("b.in","r",stdin); freopen("b.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=m;i++) s[i]=read(); temp=g=gcd(s[m],n);
for(int i=1;i<m;i++) in.insert(gcd(g,s[i]));
for(int i=2;i*i<=temp;i++) if(temp%i==0){pri.push_back(i);while(temp%i==0)temp/=i;}
if(temp!=1) pri.push_back(temp); for(auto it:in) dfs(it);
for(int i=mx=1;i*i<=g;i++,mx++) if(g%i==0&&check(i)) printf("%lld\n",n/i),exit(0);
for(int i=mx-1;i>=1;i--) if(g%(g/i)==0&&check((g/i))) printf("%lld\n",n/(g/i)),exit(0);
return 0;
}

T3 追逐

解题思路

原题,然而当时是水过去的。

一个点的贡献就是它所有和它相邻的节点的权值和减去经过它之前经过节点的权值,直接暴力枚举起点统计可以获得 70pts 。

考虑树形 DP 。 设 \(f_{i,j}\) 表示 \(i\) 节点从他的子树到他丢下 \(i\) 个磁铁的最大值,\(g_{i,j}\) 表示 \(i\) 节点从他到他的子树丢下 \(i\) 个磁铁的最大值。

转移 DP 数组直接考虑是否在这个节点放磁铁就好了,对于答案的统计直接将两个数组拼起来就好了。

由于路径的正反答案是不相同的,所以需要把连边倒过来在计算一遍。

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=1e5+10,M=110;
int n,m,ans,all,s[N],cnt[N],f[N][M],g[N][M];
int tot=1,head[N],ver[N<<1],nxt[N<<1];
vector<int> v[N];
void dfs(int x,int fa)
{
for(int i=1;i<=m;i++) f[x][i]=cnt[x],g[x][i]=cnt[x]-s[fa];
for(auto to:v[x])
{
if(to==fa) continue; dfs(to,x);
for(int i=0;i<=m;i++) ans=max(ans,f[x][i]+g[to][m-i]);
for(int i=1;i<=m;i++)
f[x][i]=max(f[x][i],max(f[to][i],f[to][i-1]+cnt[x]-s[to])),
g[x][i]=max(g[x][i],max(g[to][i],g[to][i-1]+cnt[x]-s[fa]));
}
reverse(v[x].begin(),v[x].end());
for(int i=1;i<=m;i++) f[x][i]=cnt[x],g[x][i]=cnt[x]-s[fa];
for(auto to:v[x])
{
if(to==fa) continue;
for(int i=0;i<=m;i++) ans=max(ans,f[x][i]+g[to][m-i]);
for(int i=1;i<=m;i++)
f[x][i]=max(f[x][i],max(f[to][i],f[to][i-1]+cnt[x]-s[to])),
g[x][i]=max(g[x][i],max(g[to][i],g[to][i-1]+cnt[x]-s[fa]));
}
}
#undef int
int main()
{
#define int register long long
freopen("c.in","r",stdin); freopen("c.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++) s[i]=read();
for(int i=1,x,y;i<n;i++)
x=read(),y=read(),
v[x].push_back(y),v[y].push_back(x);
for(int i=1;i<=n;i++) for(auto to:v[i]) cnt[i]+=s[to];
dfs(1,0); printf("%lld",ans);
return 0;
}

T4 字符串

解题思路

最妙的就是关于题意的转化了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<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=5e5+10;
int n,q,t;
char ch[N];
struct Node{int len,l,r,sum;};
Node const operator + (Node x,Node y)
{
Node z; z.sum=x.sum+y.sum;
z.len=max(x.r+y.l,max(x.len,y.len));
z.l=max(x.l,y.l+x.sum); z.r=max(y.r,x.r+y.sum);
return z;
}
struct Segment_Tree
{
Node tre[N<<2];
#define push_up(x) tre[x]=tre[ls]+tre[rs]
void build(int x,int l,int r)
{
if(l==r) return t=ch[l]=='C'?1:-1,tre[x]=(Node){t,t,t,t},void();
int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); push_up(x);
}
Node query(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tre[x]; int mid=(l+r)>>1;
if(L<=mid&&R>mid) return query(ls,l,mid,L,R)+query(rs,mid+1,r,L,R);
if(L<=mid) return query(ls,l,mid,L,R); return query(rs,mid+1,r,L,R);
}
}T;
#undef int
int main()
{
#define int register long long
freopen("d.in","r",stdin); freopen("d.out","w",stdout);
n=read(); scanf("%s",ch+1); T.build(1,1,n); q=read();
while(q--)
{
int l,r; l=read(); r=read(); Node temp=T.query(1,1,n,l,r);
printf("%lld\n",max(0ll,max(temp.len,max(temp.l,temp.r)))-temp.sum);
}
return 0;
}

NOIP模拟100(多校32)的更多相关文章

  1. NOIP模拟83(多校16)

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

  2. NOIP模拟92(多校25)

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

  3. NOIP模拟99(多校31)

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

  4. NOIP模拟84(多校17)

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

  5. NOIP模拟85(多校18)

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

  6. NOIP模拟86(多校19)

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

  7. NOIP模拟88(多校21)

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

  8. NOIP模拟96(多校29)

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

  9. noip模拟32[好数学啊]

    noip模拟32 solutions 真是无语子,又没上100,无奈死了 虽然我每次都觉得题很难,但是还是有好多上100的 战神都200多了,好生气啊啊啊 从题开始变难之后,我的时间分配越来越不均匀, ...

  10. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

随机推荐

  1. mysql 必知必会整理—子查询与连接表[八]

    前言 简单介绍一下子查询与连接表. 正文 什么是子查询呢? 列出订购物品TNT2的所有客户. select cust_id from orders where order_num IN (SELECT ...

  2. IIS 加载32dll失败

    前言 遇到一个这样的问题,因为在一个项目中是32位的,至于为什么是32位的呢,因为调用的都是老库,32位的,部署到iis出现错误如下: Server Error in '/' Application. ...

  3. 论文记载:A Survey on Traffic Signal Control Methods

    ABSTRACT 交通信号控制是一个重要且具有挑战性的现实问题,其目标是通过协调车辆在道路交叉口的移动来最小化车辆的行驶时间.目前使用的交通信号控制系统仍然严重依赖过于简单的信息和基于规则的方法,尽管 ...

  4. vue+mockjs模拟用户登录接口(高仿书旗)

    项目demo:http://39.103.131.74:8888/shuqi

  5. PolarDB开源未来将有哪些新动向?阿里云数据库开源负责人来解答

    简介: 在10月25日由阿里云开发者社区.PolarDB开源社区.infoQ联合举办的「开源人说」第三期--<数据库PolarDB专场>沙龙上,阿里云数据库开源负责人.数据库资深技术专家王 ...

  6. bilibili 实时平台的架构与实践

    摘要:本文由 bilibili 大数据实时平台负责人郑志升分享,基于对 bilibili 实时计算的痛点分析,详细介绍了 bilibili Saber 实时计算平台架构与实践.本次分享主要围绕以下四个 ...

  7. [Go] 浅谈 Golang Chan 通信与死锁:all goroutines are asleep - deadlock

    Channel创建方式: var c1 chan [value type] c1 = make([channel type] [value type], [capacity]) [value type ...

  8. [FAQ] Git 修改最后一次的提交人和提交时间 ?

    $ date -R Tue, 21 Mar 2021 21:08:58 +0800 $ git commit --amend  --author="xxx <xxx@email.com ...

  9. net core下链路追踪skywalking安装和简单使用

    当我们用很多服务时,各个服务间的调用关系是怎么样的?各个服务单调用的顺序\时间性能怎么样?服务出错了,到底是哪个服务引起的?这些问题我们用什么方案解决呢,以前的方式是各个系统自己单独做日志,出了问题从 ...

  10. iceoryx源码阅读(八)——IPC通信机制

    目录 1 整体结构 2 序列化与反序列化 3 类Unix系统的实现 3.1 发送函数send 3.2 接收函数receive 4 Windows系统的实现 4.1 发送函数send 4.2 接收函数r ...