李超树入门

就是用线段树去维护线段。就不写详解了

可以看传送门这篇博客。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
using namespace std;
typedef long long ll;
typedef double db;
const ll inf=0x3f3f3f3f;
const int N=5e4+5; 
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
struct Line{
	db k,b;
	int l,r;
};
struct node{
	Line li;
	bool fg;
}sg[N<<2];
il db calc(Line li,ll pos){
	return li.k*pos+li.b;
}
il long double cross (Line a,Line b){
	return (long double)(a.b-b.b)/(long double)(b.k-a.k);
}
il void update(int l,int r,int rt,Line nl){
	int mid=(l+r)>>1;
	if(nl.l<=l && nl.r>=r){
		if(!sg[rt].fg) sg[rt].fg=1,sg[rt].li=nl;
		else if(calc(nl,l)>calc(sg[rt].li,l) && calc(nl,r)>calc(sg[rt].li,r)) sg[rt].li=nl;
		else if(calc(nl,l)>calc(sg[rt].li,l) || calc(nl,r)>calc(sg[rt].li,r)){
			if(calc(nl,mid)>calc(sg[rt].li,mid)) swap(nl,sg[rt].li);
			if(cross(nl,sg[rt].li)<=mid) update(l,mid,rt<<1,nl);
			else update(mid+1,r,rt<<1|1,nl);
		}
		return ;
	}
	if(nl.l<=mid) update(l,mid,rt<<1,nl);
	if(nl.r>mid) update(mid+1,r,rt<<1|1,nl);
}
il db query(int l,int r,int rt,int P){
	if(l==r) return calc(sg[rt].li,P);
	int mid=(l+r)>>1;
	db ans=calc(sg[rt].li,P);
	if(P<=mid) ans=max(ans,query(l,mid,rt<<1,P));
	else ans=max(ans,query(mid+1,r,rt<<1|1,P));
	return ans;
} 
int T;
char op[10];
int main(){
//	std::ios::sync_with_stdio(0);cin.tie(0);
	scanf("%d",&T);
	double k,b;
	int x;
	while(T--){
		scanf("%s",op);
		if(op[0]=='P'){
			scanf("%lf%lf",&b,&k);
			b-=k;
			Line li=Line{k,b,1,N};
			update(1,N,1,li);
		}
		else{
			scanf("%d",&x);
			ll ans=(ll)query(1,N,1,x);
			printf("%lld\n",ans/100);	
		}
		
	}
	return 0;
}

BZOJ炸了,后面的题后面补

# P11728 [集训队互测 2015] Robot ## 题目描述 小 q 有 $n$ 只机器人,一开始他把机器人放在了一条数轴上,第 $i$ 只机器人在 $a_i$ 的位置上静止,而自己站在原点。 在这之后小 q 会执行一些操作,他想要命令一个机器人向左或者向右移动 $x$ 格。但是机器人似乎听不清小 q 的命令,事实上它们会以每秒 $x$ 格的速度匀速移动。 看着自己的机器人越走越远,小 q 很着急,他想知道当前离他(原点)最远的机器人有多远。 具体的操作以及询问见输入格式。注意,不同的机器人之间互不影响,即不用考虑两个机器人撞在了一起的情况。 ## 输入格式 共有 $m$ 个事件,输入将会按事件的时间顺序给出。 第一行两个正整数 $n,m$。 接下来一行 $n$ 个整数,第 $i$ 个数是 $a_i$,表示第 $i$ 个机器人初始的位置(初始移动速度为 $0$)。 接下来 $m$ 行,每行行首是一个非负整数 $t_i$,表示该事件点发生的时刻(以秒为单位)。第二个是一个字符串 $S$ ,代表操作的种类。数字与字符串之间用一个空格隔开。接下来的输入按 $S$ 的种类分类。 1. 若 $S$ 是 `command`,则接下来两个整数 $k_i,x_i$,表示小 q 对第 $k_i$ 个机器人执行了操作,该机器人的速度将会被重置,变为向数轴正方向每秒移动 $x_i$ 格(若 $x_i$ 为负数就相当于向数轴负方向每秒移动 $\lvert x_i \rvert$ 格)。保证 $1 \leq k_i \leq n$。 2. 若 $S$ 是 `query`,则你需要输出当前离原点最远的机器人有多远。 保证 $t_1 \leq t_2 \leq t_2 \leq \dots \leq t_m$。 (注:若同一时间发生多次操作,则按读入顺序依次执行) ## 输出格式 对于每个 `query` 询问,输出一行,包含一个整数表示正确的答案。 **由于本题数据量较大,建议使用高效的的输入输出方式。** ## 输入输出样例 #1 ### 输入 #1 ``` 4 5 -20 0 20 100 10 command 1 10 20 command 3 -10 30 query 40 command 1 -30 50 query ``` ### 输出 #1 ``` 180 280 ``` ## 说明/提示 ### 样例解释 - 第一个命令执行时,各个机器人的位置为:$-20, 0, 20, 100$。 - 第二个命令执行时,各个机器人的位置为:$80, 0, 20, 100$。 - 第一个询问时,各个机器人的位置为:$180, 0, -80, 100$。 - 第三个命令执行时,各个机器人的位置为:$280, 0, -180, 100$。 - 第二个询问时,各个机器人的位置为:$-20, 0, -280, 100$。 ### 数据范围 设 `command` 的个数为 $C$,`query` 的个数为 $Q$。(所以 $C + Q = m$) 对于所有的事件满足 $0 \leq t_i \leq 10^9$,对于所有的 `command` 满足 $\lvert x_i \rvert \leq 10^4$。 对于所有的机器人满足 $\lvert a_i \rvert \leq 10^9$。 所有测试数据的范围和特点如下表所示: | 测试点编号 | 数据范围 | 特殊限制 | | :----------: | :----------: | :----------: | | $1$ | $n,m\leq 2000$ | 无 | | $2$ | $n,m\leq 2000$ | 无 | | $3$ | $n,m\leq 10^5$ | $-1 \leq x_i \leq 1$ | | $4$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 两个机器人发生碰面或者超越另一个的次数 $\leq 4\times 10^5$ | | $5$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 两个机器人发生碰面或者超越另一个的次数 $\leq 4\times 10^5$ | | $6$ | $n,m\leq 10^5$ | 不会在 $t_i>0$ 时出现 `command` 操作 | | $7$ | $n,m\leq 10^5$ | 不会在 $t_i>0$ 时出现 `command` 操作 | | $8$ | $n,m\leq 10^5$ | 无 | | $9$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 无 | | $10$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 无 | 为什么WA了 ```cpp #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int MAX_N = 2e6; int n, m, lst[MAX_N], id[MAX_N]; int t[MAX_N], k[MAX_N], x[MAX_N]; ll a[MAX_N]; struct Line { ll k, b; Line(ll k = 0, ll b = 0) : k(k), b(b) { } } line[MAX_N]; inline ll get(int idx, int x) { return line[idx].k * t[x] + line[idx].b; } int tr[MAX_N << 2]; #define ls(cur) cur << 1 #define rs(cur) cur << 1 | 1 void update(int cur, int l, int r, int idx) { int mid = l + r >> 1; if (get(tr[cur], mid) < get(idx, mid)) swap(tr[cur], idx); if (l == r) return ; if (get(tr[cur], l) < get(idx, r)) update(ls(cur), l, mid, idx); if (get(tr[cur], r) < get(idx, r)) update(rs(cur), mid + 1, r, idx); } void insert(int cur, int l, int r, int L, int R, int idx) { if (L > r || l > R) return ; if (L <= l && r <= R) { update(cur, l, r, idx); return ; } int mid = l + r >> 1; if (L <= mid) insert(ls(cur), l, mid, L, R, idx); if (mid + 1 <= R) insert(rs(cur), mid + 1, r, L, R, idx); } ll query(int cur, int l, int r, int x) { ll tmp = get(tr[cur], x); if (l == r) return tmp; int mid = l + r >> 1; if (x <= mid) return max(tmp, query(ls(cur), l, mid, x)); else return max(tmp, query(rs(cur), mid + 1, r, x)); } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> m; int tot = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; line[++tot] = Line(0, a[i]); lst[i] = 0, id[i] = tot; } for (int i = 1; i <= m; i++) { string s; cin >> t[i] >> s; if (s[0] == 'c') cin >> k[i] >> x[i]; } for (int i = 1; i <= m; i++) { if (!k[i]) continue; insert(1, 0, m, lst[k[i]], i - 1, id[k[i]]); line[++tot] = Line(-line[id[k[i]]].k, -line[id[k[i]]].b); insert(1, 0, m, lst[k[i]], i - 1, tot); a[k[i]] += 1ll * (t[i] - t[lst[k[i]]]) * x[lst[k[i]]]; // ll pos = line[id[k[i]]].b + 1ll * t[i] * x[lst[k[i]]] line[++tot] = Line(x[i], a[k[i]] - 1ll * t[i] * x[i]); lst[k[i]] = i, id[k[i]] = tot; } for (int i = 1; i <= n; i++) { insert(1, 0, m, lst[i], m, id[i]); line[++tot] = Line(-line[id[i]].k, -line[id[i]].b); insert(1, 0, m, lst[i], m, tot); } for (int i = 1; i <= m; i++) if (!k[i]) cout << query(1, 0, m, i) << '\n'; return 0; } ```
最新发布
10-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值