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. 重新点亮shell————sed的替换[十]

    前言 简单介绍一下sed 和 awk. 正文 这两个和vim的区别: vim 是交互式和 他们是非交互式 vim是文件操作模式与他们是行交互模式 sed sed 的 模式空间. sed的基本工作方式是 ...

  2. webpack中常见的Plugin?解决了什么问题?

    一.是什么 Plugin(Plug-in)是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能 是一种遵循一定规范的应用程序接口编写出来的程序,只能运行在程序规定的系统下,因为其需要调用原纯 ...

  3. 使用Skyline 新型UI管理OpenStack技术方案

    使用Skyline 新型UI管理OpenStack [摘要] Skyline 是一个经过 UI 和 UE 优化过的 OpenStack 仪表盘,支持 OpenStack Train 及以上版本.Sky ...

  4. 1.css的初认识

    1.什么是CSS? Cascading Style Sheet 层叠级联样式表 CSS:表现层(美化网页) 字体.颜色.边距.高度.宽度.背景图片.网页定位.网页浮动.... 2.CSS发展史 CSS ...

  5. 力扣412(java)-Fizz Buzz(简单)

    题目: 给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中: answer[i] == "FizzB ...

  6. 力扣686(java)-重复叠加字符串匹配(中等)

    题目: 给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1. 注意:字符串 "abc" 重复叠加 ...

  7. 谈谈PolarDB-X在读写分离场景的实践

    简介: 针对写少读多的业务可以考虑通过添加数据库节点来使其达到提升性能的目的,但添加节点,往往涉及到数据的搬迁,扩容周期比较长,很难应对徒增的业务流量,这个时候可以考虑采用读写分离的方式,将读写流量做 ...

  8. 进一步释放技术红利,阿里云推出全新内存增强型实例re6,性能提升30%

    5月7日,国内最大云计算厂商阿里云宣布推出全新一代内存增强型实例,提供1:14.8超大内存比内存容量,满足内存型数据库如SAP HANA.Redis等应用,充分释放技术红利,帮助线下企业快速上云,完成 ...

  9. 37 手游基于 Flink CDC + Hudi 湖仓一体方案实践

    ​简介: 介绍了 37 手游为何选择 Flink 作为计算引擎,并如何基于 Flink CDC + Hudi 构建新的湖仓一体方案. 本文作者是 37 手游大数据开发徐润柏,介绍了 37 手游为何选择 ...

  10. [FAQ] Sortable 拖拽组件, 火狐浏览器中打开新窗口问题

      Q:用了 sortable 组件,在火狐浏览器中进行拖拽时,会打开新窗口 ? Sortable组件地址,https://github.com/SortableJS/Sortable 当前处理方式 ...