P3309 [SDOI2014] 向量集

\[ans=\max\{zx+wy\}\to \\\frac{ans}{w}=\max\{\frac{z}{w}x+y\} \]

斜率优化的形式,答案一定在上凸包上。而这道题要维护区间凸包。

考虑线段树,预处理区间凸包复杂度是 \(O(len)\) 的,这样复杂度是 \(O(n^2)\) 的。

但是每个区间只有在所有凸包全部插入后才有可能被询问到,所以每个区间实际上只用预处理一次,类似二进制分组。所以复杂度 \(O(n\log n)\),而询问在每个区间的凸包上二分即可,\(O(n\log^2n)\)

luogu 最优解到底多快啊,怎么 1.5s 还卡不过去 /fn。

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define intz(x,y) memset((x),(y),sizeof((x)))
//void write(int x){cout<<x<<' ';}
//void write(pii x){cout<<"P("<<x.fi<<','<<x.se<<")\n";}
//void write(vector<auto>x){for(auto i:x)write(i);cout<<'\n';}
//void write(auto *a,int l,int r){for(int i=l;i<=r;i++)write(a[i]);cout<<'\n';}
#define pcount(x) __builtin_popcount(x)
inline void cmx(auto &x,ll y){if(y>x)x=y;}
const int N=4e5+5;
pii a[N];ll lst;
struct node{int l,r,mx,my;bool fl;basic_string<pii>w;}t[N<<2];
void build(int u,int l,int r){
	t[u]={l,r};if(l==r)return;int mid=l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
inline bool chk(pii &x,pii &y,pii &z){return 1ll*(x.se-y.se)*(z.fi-y.fi)>1ll*(z.se-y.se)*(x.fi-y.fi);}
inline void get(int &u){
	basic_string<pii>p;
	t[u].fl=1;int l=t[u].l,r=t[u].r;
	for(int i=l;i<=r;i++)p.pb(a[i]);
	sort(p.begin(),p.end());
	for(pii z:p){
		while(t[u].w.size()>1){
			pii x=t[u].w.back(),y=t[u].w[t[u].w.size()-2];
			if(!chk(x,y,z))t[u].w.pop_back();else break;
		}t[u].w.pb(z);
	}
}
void upd(int u,int &d){
	cmx(t[u].mx,a[d].fi),cmx(t[u].my,a[d].se);
	if(t[u].l==t[u].r)return;
	int mid=t[u].l+t[u].r>>1;
	(d<=mid?upd(u<<1,d):upd(u<<1|1,d));
}
inline ll calc(int u,int &x,int &y){
	if(!y)return 1ll*t[u].mx*x;
	if(!x)return 1ll*t[u].my*y;
	int l=0,r=t[u].w.size()-2,mid;
	while(l<=r)(mid=l+r>>1,1ll*(t[u].w[mid+1].se-t[u].w[mid].se)*y>=1ll*(-x)*(t[u].w[mid+1].fi-t[u].w[mid].fi)?l=mid+1:r=mid-1);
	return (1ll*x*t[u].w[l].fi+1ll*t[u].w[l].se*y);
}
ll query(int u,int l,int r,int &x,int &y){
	if(t[u].l>=l&&t[u].r<=r){
		if(!t[u].fl)get(u);
		return calc(u,x,y);
	}
	int mid=t[u].l+t[u].r>>1;ll mx=-1e18;
	if(l<=mid)mx=query(u<<1,l,r,x,y);
	if(r>mid)cmx(mx,query(u<<1|1,l,r,x,y));
	return mx;
}
inline int decode(int x){return x^(lst&0x7fffffff);}
inline void UesugiErii(){
	int n,tot=0;char C;cin>>n>>C;
	build(1,1,n);
	char op;int x,y,l,r;
	while(n--){
		cin>>op>>x>>y;
		if(op=='A'){
			if(C!='E')x=decode(x),y=decode(y);
			a[++tot]=mp(x,y);upd(1,tot);
		}else{
			cin>>l>>r;
			if(C!='E')x=decode(x),y=decode(y),l=decode(l),r=decode(r);
			cout<<(lst=query(1,l,r,x,y))<<'\n';
		}
	}
}
signed main(){
	//IO();
	cfast;
	int _=1;//cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2025-12-04 09:45  Uesugi1  阅读(0)  评论(0)    收藏  举报