7.22模拟赛
7.22模拟赛#
甲国的军队 #
简单的贪心,手玩一下就能得出结论
假设现在攻打两个城市 ,
先打 的代价为
先打 的代价为
按 小于 排序就行
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
struct war{
int a,b;
inline bool operator <(const war c)const {
return a+c.b<b+c.a;
}
}a[N];
signed main(){
int T=read();
while(T--){
int n=read();
for(int i=1;i<=n;++i){
a[i].a=read(),a[i].b=read();
a[i].b=max(a[i].a,a[i].b);
}
sort(a+1,a+n+1);
long long now=0,ans=0;
for(int i=1;i<=n;++i){
if(now<a[i].b){
ans+=a[i].b-now;
now=a[i].b-a[i].a;
}
else
now-=a[i].a;
}
printf("%lld\n",ans);
}
}
虚弱 #
这个东西带有绝对值,画成有关 的图像显然是中间小两边大
显然是下凸函数,可以三分
每次 跑一遍
注意精度
code:
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-11
const int N=2e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n;
double a[N];
double b[N],s[N],f[N],g[N];
double sum,ans;
inline double check(double x){
for(int i=1;i<=n;++i) b[i]=(double)a[i]-x;
for(int i=1;i<=n;++i) s[i]=s[i-1]+b[i];
f[1]=g[1]=s[1];
double mx=-1e18,mn=1e18;
for(int i=2;i<=n;++i) f[i]=max(f[i-1],s[i]),g[i]=min(g[i-1],s[i]);
//for(int i=1;i<=n;++i) printf("%lf %lf %lf %lf\n",b[i],s[i],f[i],g[i]);
for(int i=1;i<=n;++i) mx=max(mx,s[i]-g[i-1]),mn=min(mn,s[i]-f[i-1]);
return max(fabs(mx),fabs(mn));
}
signed main(){
n=read();
for(int i=1;i<=n;++i){
scanf("%lf",&a[i]);
s[i]=s[i-1]+a[i];
}
double l=-1e4,r=1e4;
while(r-l>eps){
double mid=(r-l)/3;
double nowl=l+mid,nowr=r-mid;
//printf("%lf %lf %lf %lf %lf\n",l,r,mid,nowl,nowr);
if(check(nowl)<check(nowr)) r=nowr,ans=nowl;
else l=nowl,ans=nowr;
}
printf("%.6lf\n",check(ans));
}
萨鲁曼的半兽人 #
这题容易想到先跑 ,然后搞一个
我们设 表示 满足 是回文串的左侧最远的位置 , 表示连好前 个字符所需的最小次数
转移方程式 ,时间复杂度
考虑这个过程可以用线段树维护,将时间优化到
考场上调了 最后发现 写炸了,
考场后发现解法很多,比如堆优化贪心,单调栈优化 ,甚至还有随机化,而且最劣是 的暴力也能过?
事实证明,智商不够只能用数据结构 ,代码相对来说巨长
退火教主
upd : 由于数据太弱,我个人重新造了一些数据,足以卡掉随机化的解法以及暴力的解法 (貌似还卡掉了 的哈希?不是很理解)
code:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int inf=2e9;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
namespace ST{
struct node{
int mn;
int l,r;
}t[N<<2];
#define lsp p<<1
#define rsp p<<1|1
inline void push_up(int p){
t[p].mn=min(t[lsp].mn,t[rsp].mn);
}
inline void build(int p,int l,int r){
t[p]={inf,l,r};
if(l==r) return;
int mid=l+r>>1;
build(lsp,l,mid);
build(rsp,mid+1,r);
}
inline void update(int p,int x,int k){
if(t[p].l==t[p].r){
t[p].mn=k;
return;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid) update(lsp,x,k);
else update(rsp,x,k);
push_up(p);
}
inline int query(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)
return t[p].mn;
int mid=t[p].l+t[p].r>>1,res=inf;
if(l<=mid) res=min(res,query(lsp,l,r));
if(mid<r) res=min(res,query(rsp,l,r));
return res;
}
}
int n,m;
char s[N],t[N];
int p[N],g[N],f[N],pre[N];
inline void pre_work(){
for(int i=1;i<=n;++i){
t[i*2-1]='#';
t[i*2]=s[i];
}
t[0]='$',t[n*2+1]='#',t[2*n+2]='&';
m=2*n+1;
//for(int i=1;i<=2*n+1;++i) cout<<t[i]<<" ";cout<<endl;
}
inline void manacher(){
int mr=0,mid=0;
memset(p,0,sizeof(p));
for(int i=1;i<=m;++i){
p[i]=min(p[2*mid-i],p[mr-i]);
while(i-p[i]&&t[i-p[i]]==t[i+p[i]]) ++p[i];
if(i+p[i]>mr){
mr=i+p[i];
mid=i;
}
}
//for(int i=1;i<=m;++i) cout<<p[i]<<" ";cout<<endl;
}
inline int doge_pride(){
for(int i=1;i<=m;++i) f[i]=inf;
f[0]=f[1]=0;
for(int i=1;i<=m;++i) pre[i]=inf;
ST::build(1,1,m);
ST::update(1,1,0);
for(int i=1;i<=m;++i){
if(i+p[i]-1<=m) pre[i+p[i]-1]=min(pre[i+p[i]-1],i-p[i]+1);
if(i!=p[i]) continue;
if(i+p[i]-1>=m) f[m]=0;
else f[i+p[i]-1]=0;
}
//for(int i=1;i<=m;++i) cout<<f[i]<<" ";cout<<endl;
for(int i=2;i<=m;++i){
f[i]=min(f[i],ST::query(1,pre[i],i-1)+1);
ST::update(1,i,f[i]);
//cout<<i<<" "<<f[i]<<" "<<i-p[i]<<endl;
}
//for(int i=1;i<=m;++i) cout<<f[i]<<" ";cout<<endl;
return f[m];
}
signed main(){
while(scanf("%s",s+1)!=EOF){
n=strlen(s+1);
//if(n%2==0) continue;
pre_work();
manacher();
printf("%d\n",doge_pride());
}
}
序列 #
比较容易想到 的贪心:
- 分别找到下标编号为奇数中权值最小的位置和下标编号为偶数中权值最小的位置,直接输出,并将其从原序列中删掉
- 重新编号
显然这样的做法是正确的,因为这样就相当于先把中间的两两拿出来再拿两边的
这样可以打出 的暴力
考虑这个东西可以用线段树维护,我们只需要维护:
一个区间内编号为奇数的最小值和编号为偶数的最小值
区间翻转操作
此题结束
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现