F. Lena and Queries
我的第一道cdq分治,简直绝妙。。由于点会被删除,相当于每个点有一个作用区间 [l,r] 。对询问分治,每次在分治区间内求凸壳(只使用作用区间包含分治区间的那些点求),更新答案。至于每个点出现在了哪些区间,用线段树维护。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 300010;
const ll INF = 2e18;
int t[maxn];
ll a[maxn];
ll b[maxn];
ll ans[maxn];
int r[maxn];
inline int getID(int l,int r){
return (l+r)|(l<r);
}
struct Point{
ll x,y;
Point(ll x,ll y):x(x),y(y){
}
Point(){
}
bool operator<(const Point &other)const{
if(x!=other.x){
return x<other.x;
}
return y>other.y;
}
};
Point ch[maxn];
vector<Point> pts[maxn<<1];
void update(int tl,int tr,int l,int r,Point pt){
if(l == tl && r == tr){
pts[getID(l,r)].push_back(pt);
return;
}
int mid = (tl+tr)>>1;
if(r <= mid){
update(tl,mid,l,r,pt);
}else{
if(l > mid){
update(mid+1,tr,l,r,pt);
}else{
update(tl,mid,l,mid,pt);
update(mid+1,tr,mid+1,r,pt);
}
}
}
int sz; //ConvexHull's size
int n;
void ConvexHull(int id){
sort(pts[id].begin(),pts[id].end());
sz = 0;
Point pre = Point(-INF,-INF);
for(int i=0;i<(int)pts[id].size();i++){
Point pt = pts[id][i];
if(pt.x == pre.x){
continue;
}
pre = pt;
if(sz<2){
ch[sz++] = pt;
}else{
while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
sz--;
}
ch[sz++] = pt;
}
}
}
inline ll calc(int ptid,int qid){
return ch[ptid].y+ch[ptid].x*a[qid];
}
ll bs(int l,int r,int qid){
int L = l;
int R = r;
ll res = -INF;
while(l<=r){
int mid = (l+r)>>1;
ll mval = calc(mid,qid);
res = max(res,mval);
if(mid > L && calc(mid-1,qid) > mval){
r = mid-1;
}else if(mid < R && calc(mid+1,qid) > mval){
l = mid+1;
}else{
break;
}
}
return res;
}
void cdq(int l,int r){
int mid = (l+r)>>1;
if(l<r)cdq(l,mid);
if(l<r)cdq(mid+1,r);
ConvexHull(getID(l,r));
for(int i=l;i<=r;i++){
if(t[i] == 3){
ans[i] = max(ans[i],bs(0,sz-1,i));
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&t[i]);
if(t[i] == 1){
scanf("%I64d%I64d",&a[i],&b[i]);
r[i] = n;
}else{
scanf("%I64d",&a[i]);
if(t[i] == 2){
r[a[i]] = i-1;
}
}
ans[i] = -INF;
}
for(int i=1;i<=n;i++){
if(t[i] == 1){
if(i+1<=r[i])update(1,n,i+1,r[i],Point(a[i],b[i]));
}
}
cdq(1,n);
for(int i=1;i<=n;i++){
if(t[i] == 3){
if(ans[i] == -INF){
printf("EMPTY SET\n");
}else{
printf("%I64d\n",ans[i]);
}
}
}
return 0;
}