[省选联考 2020 A/B 卷] 冰火战士
[省选联考 2020 A/B 卷] 冰火战士
tag
树状数组二分
对树状数组的理解加深了!
转化题意
动态维护一个单调不降和一个单调不增序列,每次修改后输出两序列取最小值后的最大值和其最大位置。
思路
首先,阅读原题,知道最后答案一定是某个战士的温度,所以我们将温度离散化。
再次阅读,发现冰系是一个(以温度为自变量的)单调不降序列,每次修改一个战士就是修改一段后缀。火系相反,修改前缀。
深度阅读,发现题目其实就是求两个序列的交点。
于是转化成上述题意。
考虑二分答案求出两点的交,即温度最大的冰系能量和不大于火系能量和的位置。如果用树状数组动态维护每次查询的话,时间复杂度是两个 ,无法通过。
实际上,树状数组也是可以二分的。
回忆树状数组的树形结构,一个点 实际上存储了 到 的所有信息,所以我们在树状数组上二分,实际上就是像倍增一样,从大到小依次枚举这个点加上 的祖先,能跳则跳。
于是我们就可以A了这题了。注意我这里存储火系前缀和的方式是记录一个全局和再在树状数组上减去。
最后答案乘二。
实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
inline int read(){
int x=0,w=0;char c=getchar();
while(!isdigit(c)) w|=c=='-',c=getchar();
while(isdigit(c)) x=x*10+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=4e6+10;
int n,b[maxn],cnt,sumfire;
struct BIT{
int c[maxn];
inline void update(int x,int k){for(;x<=cnt;x+=x&-x)c[x]+=k;}
}S1,S2;
inline int query(int x){
if(x<1 or x>cnt) return 0;
int ans1=0,ans2=sumfire;
for(;x;x-=x&-x) ans1+=S1.c[x],ans2+=S2.c[x];
return min(ans1,ans2);
}
struct query{
bool type;
int t,v,op;
}e[maxn];
inline void work(){
n=read();
for(int i=1;i<=n;i++)
if((e[i].op=read())==1)
e[i].type=read(),e[i].t=b[++cnt]=read(),e[i].v=read();
else e[i]=e[read()],e[i].op=2,e[i].v=-e[i].v;
sort(b+1,b+1+cnt);
cnt=unique(b+1,b+1+cnt)-b-1;
for(int i=1;i<=n;i++) e[i].t=lower_bound(b+1,b+1+cnt,e[i].t)-b;
for(int i=1;i<=n;i++){
if(e[i].type==0) S1.update(e[i].t,e[i].v);
else S2.update(e[i].t+1,-e[i].v),sumfire+=e[i].v;
int x1=0,sum=-sumfire;
for(int j=21;~j;j--){
int to=x1|(1<<j),zp;
if(to<=cnt and (zp=sum+S1.c[to]-S2.c[to])<=0) sum=zp,x1=to;
}
int ans1=query(x1),x2=x1+1,ans2=query(x2);
if(ans1<=0 and ans2<=0)puts("Peace");
else if(ans1>ans2) printf("%d %d\n",b[x1],ans1<<1);
else {
int p=0,sum=sumfire;
for(int j=21;~j;j--){
int to=p|(1<<j),zp;
if(to<=cnt and (zp=sum+S2.c[to])>=ans2) sum=zp,p=to;
}//因为现在的情况一定是火系战士能量低所以光用火系的找答案就行了
printf("%d %d\n",b[p],sum<<1);
}
}
}
}
signed main(){
star::work();
return 0;
}
其他
- 三分是不正确的因为这玩意的峰不知道在哪而且会有平台。
- 如果用其他方式存火系的信息请务必考虑是否算进了当前点的值。
听说这题数据特水每次暴力移动上次答案的指针都能过- 输出太大在洛谷上OLE了,但LOJ上可以提交,希望管理员修复一下~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现