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组合索引

    MySQL组引合索优化SQL 我的场景 200w左右的数据,后面会更多 使用定时任务爬取数据插入到自己的数据库.要保证数据的唯一性,所以我用了组合唯一索引. 表结构 最初的组合索引 SQL执行和exp ...

  2. vue 插件(swiper)使用

    两种方法: 1... 打开https://www.swiper.com.cn/download/index.html 下载css,js... 把js,css引入public里面的index.html文 ...

  3. SVN Windows10的安装

    SVN Windows安装与配置 先去到官网的下载链接:Download Apache Subversion Sources 然后点这个 binary packages 在这里能看到大多数的操作系统的 ...

  4. 力扣275(jav&python)-H 指数 II(中等)

    题目: 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 .计算并返回该研究者的 h 指数. h ...

  5. SKG 渠道中台借助 SAE + 大禹打造云原生 DevOPS,提效 60%

    简介: 新零售标杆 SKG 全面拥抱 Serverless,敏捷交付! 作者:陈列昂(SKG).昕辰.龙琛.黛忻 项目背景 未来穿戴健康科技股份有限公司(SKG)是一家专注为个人与家庭提供智能可穿戴健 ...

  6. 阿里云CDN产品经理陈章炜:边缘创新技术和落地实践

    简介: CDN除了加速外,不断被赋予更多价值.在阿里云CDN推出的<极速奔跑吧 2021>首场直播中,阿里云架构师和产品经理不仅对近期阿里云发布的CDN产品最佳实践图进行了详细解读,还对C ...

  7. 10种编程语言实现Y组合子

    简介: Y组合子是Lambda演算的一部分,也是函数式编程的理论基础.它是一种方法/技巧,在没有赋值语句的前提下定义递归的匿名函数,即仅仅通过Lambda表达式这个最基本的"原子" ...

  8. 达摩院重要科技突破!空天数据库引擎Ganos解读

    简介: Ganos空天数据库引擎是李飞飞带领的达摩院数据库与存储实验室研发的新一代位置智能引擎,采用了平台即服务.多模融合.计算下推和云原生全新处理架构,为政府.企事业单位.泛互联网客户提供移动对象. ...

  9. Spring Boot Serverless 实战系列“架构篇” 首发 | 光速入门函数计算

    ​简介:如何以 Serverless 的方式运行 Spring Boot 应用? ​ 作者 | 西流(阿里云函数计算专家) Spring Boot 是基于 Java Spring 框架的套件,它预装了 ...

  10. 修复 Debian 安装 dotnet 失败 depends on ca-certificates

    本文记录我在 Debian 安装 dotnet 失败,报错信息是 packages-microsoft-prod depends on ca-certificates; however: Packag ...