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. 有用的JavaScript技巧

    首次为变量赋值时务必使用var关键字 变量没有声明而直接赋值得话,默认会作为一个新的全局变量,要尽量避免使用全局变量. 使用===取代== ==和!=操作符会在需要的情况下自动转换数据类型.但===和 ...

  2. python websocket 参数

    websocket中就有建立连接connect.发送消息send等函数可供使用,但是websocket.WebSocketApp将这些都封装好了,只用在实例化的时候传入自定义函数即可,更方便.因此这里 ...

  3. Snowflake核心技术解读系列——架构设计

    ​简介:Snowflake取得了巨大的商业成功,技术是如何支撑起它的千亿美元市值呢?它技术强在哪?本文为大家倾情解读Snowflake的核心技术原理. 背景:2020年9月16日,Snowflake成 ...

  4. [Go] 选择 Beego 的三个理由

    1. 项目支持角度较其它框架考虑的多一些,比如:目录结构的简单约定,内置项目配置读取,内置bee脚手架,热重载特性 等. (实际这些 feature 都可以找到 golang 专精的组件引入起来,效果 ...

  5. dotnet OpenXML 文本删除线解析方法

    本文来告诉大家如何解析读取在 OpenXML 里面存放的文本删除线,本文使用 PowerPoint 作为例子来告诉大家如何读取然后在 WPF 应用里面显示 在开始之前,期望大家已了解如何在 dotne ...

  6. WPF 获取本机所有字体拿到每个字符的宽度和高度

    本文主要采用 GlyphTypeface 类尝试获取每个字符的宽度和高度的值,尽管这个方法和最终 WPF 布局使用的文本的宽度和高度是不相同的,但是依然可以作为参考 获取系统字体文件夹的文件 系统字体 ...

  7. 2019-10-14-云之幻-UWP-视频教程

    title author date CreateTime categories 云之幻 UWP 视频教程 lindexi 2019-10-14 21:8:26 +0800 2019-10-14 21: ...

  8. ruby操作excel

    操作xlsx axlsx插件 操作xls spreadsheet插件

  9. 【项目学习】Timeswap:第一个完全去中心化的基于 AMM 的货币市场协议

    总览 Timeswap 是世界上第一个完全去中心化的基于 AMM 的货币市场协议,无需预言机或清算人即可工作. Timeswap 采用 3 变量来维持 AMM 的运作.它通过允许用户决定他们的风险状况 ...

  10. Echarts设置饼状图保证你看的明明白白

    简单的饼状图 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...