题意:要求在平面直角坐标系下维护两个操作:

1.在平面上加入一条线段。记第i条被插入的线段的标号为i。 
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。

解题关键:注意标志的作用,注意虽然存的是索引,但是线段树的范围是天数的范围,也就是线段树是依据天数建的树

复杂度:$O(nlogn)$

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=;
double a[N],b[N],ans;
int tr[N<<];
bool check(int x,int y,int t){
return a[x]+b[x]*(t-)>a[y]+b[y]*(t-);
} void update(int rt,int l,int r,int now){
if(l==r){
if(check(now,tr[rt],l)) tr[rt]=now;
return;
}
int mid=(l+r)>>;
if(b[now]>b[tr[rt]]){
if(check(now, tr[rt], mid)) update(rt<<,l, mid, tr[rt]),tr[rt]=now;//更新的最后一个是tr[rt]?存的是下标,询问时肯定按log的顺序,而此时now的掌控区间已经确定,需要更新tr[rt]的掌控区间
else update(rt<<|, mid+, r, now);
}
else{
if(check(now,tr[rt],mid)) update(rt<<|, mid+, r, tr[rt]),tr[rt]=now;
else update(rt<<, l, mid, now);
}
} void query(int rt,int l,int r,int now){
ans=max(ans,a[tr[rt]]+b[tr[rt]]*(now-));
if(l==r) return;
int mid=(l+r)>>;
if(now<=mid) query(rt<<, l, mid, now);
else query(rt<<|, mid+, r, now);
} int main(){
int n,m=,c;
char s[];
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%s",s);
if(s[]=='P'){
m++;
scanf("%lf%lf",a+m,b+m);
update(, ,n, m);//线段树中存的是下标,而值需要计算
}else{
scanf("%d",&c);
ans=;
query(, ,n, c);
printf("%d\n",(int)ans/);
}
}
return ;
}

模板2:主要是query函数的两种写法,此写法不需要建全局变量

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=;
double a[N],b[N],ans;
int tr[N<<];
bool check(int x,int y,int t){
return a[x]+b[x]*(t-)>a[y]+b[y]*(t-);
} void update(int rt,int l,int r,int now){
if(l==r){
if(check(now,tr[rt],l)) tr[rt]=now;
return;
}
int mid=(l+r)>>;
if(b[now]>b[tr[rt]]){
if(check(now, tr[rt], mid)) update(rt<<,l, mid, tr[rt]),tr[rt]=now;//更新的最后一个是tr[rt]?存的是下标,询问时肯定按log的顺序,而此时now的掌控区间已经确定,需要更新tr[rt]的掌控区间
else update(rt<<|, mid+, r, now);
}
else{
if(check(now,tr[rt],mid)) update(rt<<|, mid+, r, tr[rt]),tr[rt]=now;
else update(rt<<, l, mid, now);
}
} double query(int rt,int l,int r,int now){
double ans=max(0.0,a[tr[rt]]+b[tr[rt]]*(now-));
if(l==r) return ans;
int mid=(l+r)>>;
if(now<=mid) ans=max(ans,query(rt<<, l, mid, now));
else ans=max(ans,query(rt<<|, mid+, r, now));
return ans;
} int main(){
int n,m=,c;
char s[];
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%s",s);
if(s[]=='P'){
m++;
scanf("%lf%lf",a+m,b+m);
update(, ,n, m);//线段树中存的是下标,而值需要计算
}else{
scanf("%d",&c);
double ans=query(, ,n, c);
printf("%d\n",(int)ans/);
}
}
return ;
}

最新文章

  1. SQL Tuning 基础概述09 - SQL Access Advisor
  2. NServiceBus 结合 RabbitMQ 使用
  3. MySQL安装问题:Unable to update security settings解决方案
  4. UVaLive 6697 Homework Evaluation (DP)
  5. php session学习笔记(实例代码)
  6. libvirt TLS
  7. Spark里边:Worker源代码分析和架构
  8. a web-based music player(GO + html5)
  9. ABP应用层——审计日志
  10. Slf4j+Log4j日志框架入门
  11. 小白的Python之路 day1 字符编码
  12. 第一届“百度杯”信息安全攻防总决赛_Upload
  13. yarn web ui 参数详解
  14. vue常用笔记
  15. php获取数据库结构
  16. IntelliJ Idea设置单击打开文件或者双击打开文件、自动定位文件所在的位置
  17. 腾讯云分布式高可靠消息队列CMQ架构
  18. SpringBoot整合mybatis踩坑
  19. 对spring boot 之AutoConfiguration 的理解
  20. Decrypting OWIN Authentication Ticket

热门文章

  1. Kattis - names Palindrome Names 【字符串】
  2. path.join()和path.resolve()区别
  3. OJ的runtime error exit code对应SIGTERM代码
  4. 什么是gitlab CI ?CI代表什么?
  5. awk过滤磁盘使用率
  6. 解决COMODO Internet Security更新慢或失败的问题
  7. Vim的map
  8. Ubuntu14 下安装jdk1.8
  9. HTML5 学习记录——2
  10. hihocoder-1274 自行车架(高维dp)