【UOJ# 191】【集训队互测2016】—Unknown(线段树分治)

传送门


显然的斜率式子推一下,维护一个斜率递减的凸壳二分
由于有删除
所以每次加一个点不合并左右儿子
当这一层的下一个节点被填满时再合并
这样至少要删除O(2k)O(2^k)次才会有一次O(2k)O(2^k)的重构
修改复杂度就是对的
询问的时候loglog个节点
前面每个最多都只会递归左右儿子,最后一个会递归loglog个儿子
节点数复杂度仍然是O(log)O(log)

不过注意由于这里线段树长度不是2k2^k
对于某些叶子节点前面也对着一些需要pushuppushup

复杂度O(nlog2n)O(nlog^2n)
空间O(nlogn)O(nlogn)

开始的时候斜率式子推反了没发现
在网上找了个数据调
调了半天不知道哪里有问题
结果那sb博主造的数据是错的
还在那里得意洋洋的说找了几个程序都没跑过

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>
cs int mod=998244353;
inline void chemx(ll &a,ll b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
struct pt{
	int x,y;
	pt(int _x=0,int _y=0):x(_x),y(_y){}
	friend inline pt operator +(cs pt &a,cs pt &b){
		return pt(a.x+b.x,a.y+b.y);
	}
	friend inline pt operator -(cs pt &a,cs pt &b){
		return pt(a.x-b.x,a.y-b.y);
	}
	friend inline ll operator *(cs pt &a,cs pt &b){
		return 1ll*a.x*b.y-1ll*a.y*b.x;
	}
	friend inline bool operator <(cs pt &a,cs pt &b){
		return a.x==b.x?a.y<b.y:a.x<b.x;
	}
};
struct node{
	vector<pt> vec;
	node(){vec.clear();}
	inline void pb(cs pt &x){
		while(vec.size()>1&&(x-vec[vec.size()-2])*(vec[vec.size()-1]-vec[vec.size()-2])<=0)vec.pop_back();
		vec.pb(x);
	}
	friend inline node merge(cs node &a,cs node &b){
		node c;
		int i=0,j=0;
		while(i<a.vec.size()&&j<b.vec.size()){
			if(a.vec[i]<b.vec[j])c.pb(a.vec[i]),i++;
			else c.pb(b.vec[j]),j++;
		}
		while(i<a.vec.size())c.pb(a.vec[i]),i++;
		while(j<b.vec.size())c.pb(b.vec[j]),j++;
		return c;
	}
	inline bool check(cs pt &a,cs pt &b,cs pt &c){
		pt d=b-a;
		return d*c<=0;
	}
	inline ll query(pt k){
		int l=0,r=(int)vec.size()-2;
		while(l<=r){
			int mid=(l+r)>>1;
			if(check(vec[mid],vec[mid+1],k))l=mid+1;
			else r=mid-1;
		}
		return k*vec[l];
	}
};
cs int N=300005;
node tr[N<<2];
int last[N],vis[N<<2];
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
inline void build(int u,int l,int r,int dep){
	vis[u]=0,tr[u].vec.clear(),last[dep]=0;
	if(l==r)return;
	build(lc,l,mid,dep+1),build(rc,mid+1,r,dep+1);
}
inline void pushup(int u){
	vis[u]=1,tr[u]=merge(tr[lc],tr[rc]);
}
inline void insert(int u,int l,int r,int p,pt k,int dep){
	if(r==p){
		int x=last[dep];
		if(x)pushup(x);
		if(l==r)last[dep]=0;else last[dep]=u;
	}
	if(l==r){tr[u].pb(k);return;}	
	if(p<=mid)insert(lc,l,mid,p,k,dep+1);
	else insert(rc,mid+1,r,p,k,dep+1);
}
void delet(int u,int l,int r,int p,int dep){
	tr[u].vec.clear(),vis[u]=0;
	if(last[dep]==u)last[dep]=0;
	if(l==r)return;
	if(p<=mid)delet(lc,l,mid,p,dep+1);
	else delet(rc,mid+1,r,p,dep+1);	
}
inline ll query(int u,int l,int r,int st,int des,pt k){
	if(l==r){return tr[u].query(k);}
	if(st<=l&&r<=des){
		if(vis[u])return tr[u].query(k);
		else return max(query(lc,l,mid,st,des,k),query(rc,mid+1,r,st,des,k));
	}
	ll res=-2e18;
	if(st<=mid)chemx(res,query(lc,l,mid,st,des,k));
	if(mid<des)chemx(res,query(rc,mid+1,r,st,des,k));
	return res;
}
int n,m,ans,mx;
signed main(){
	read(),m=read();
	while(m){
		ans=n=0;
		mx=min(m,300000);
		build(1,1,mx,1);
		for(int i=1;i<=m;i++){
			int op=read();
			if(op==1){
				int x=read(),y=read();
				insert(1,1,mx,++n,pt(x,y),1);
			}
			else if(op==2){
				delet(1,1,mx,n--,1);
			}
			else {
				int l=read(),r=read(),x=read(),y=read();
				ll res=query(1,1,mx,l,r,pt(x,y));
				ans^=(res%mod+mod)%mod;
			}
		}
		cout<<ans<<'\n';
		m=read();
	}
}
posted @ 2019-09-16 15:01  Stargazer_cykoi  阅读(99)  评论(0编辑  收藏  举报