ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://uoj.ac/problem/191

zkw线段树维护区间凸包,由于凸包的上传需要归并排序,为保证均摊复杂度,一个点只在同一层的右边一个点对应的区间插入完毕时才上传信息,删除时则清除被删除叶子到根的路径的信息,查询则在凸包上二/三分。

#include<bits/stdc++.h>
typedef long long i64;
const int M=1e5,N=300007,P=998244353,mx=524288;
char ib[M+7],*ip=ib+M;
int G(){
    if(ip==ib+M)fread(ip=ib,1,M,stdin)[ib]=0;
    return *ip++;
}
int _(){
    int x=0,f=1;
    if(ip<ib+M-100){
        while(*ip<48)*ip++=='-'?f=-1:0;
        while(*ip>47)x=x*10+*ip++-48;
    }else{
        int c=G();
        while(c<48)c=='-'?f=-1:0,c=G();
        while(c>47)x=x*10+c-48,c=G();
    }
    return x*f;
}
struct pos{
    int x,y;
    i64 operator*(const pos&w)const{return i64(x)*w.y-i64(y)*w.x;}
    pos operator-(const pos&w)const{return (pos){x-w.x,y-w.y};}
}ps[20][N],*tr[mx+N],*_a;
int cnt[mx+N],now=0,_p;
void ins(const pos&p){
    if(_p&&_a[_p-1].x==p.x){
        if(_a[_p-1].y>=p.y)return;
        --_p;
    }
    while(_p>1&&(_a[_p-2]-_a[_p-1])*(p-_a[_p-1])<=0)--_p;
    _a[_p++]=p;
}
void up(int w){
    if(cnt[w])return;
    _a=tr[w];_p=0;
    pos*ls=tr[w<<1],*le=ls+cnt[w<<1],*rs=tr[w<<1^1],*re=rs+cnt[w<<1^1];
    while(ls!=le&&rs!=re)ins(ls->x<rs->x?*ls++:*rs++);
    while(ls!=le)ins(*ls++);
    while(rs!=re)ins(*rs++);
    cnt[w]=_p;
}
void push(){
    int x=_(),y=_(),w=mx+(++now);
    cnt[w]=1;
    *tr[w]=(pos){x,y};
    for(;w&1;w>>=1,up(w-1));
}
void pop(){
    for(int w=mx+now-->>1;cnt[w]>0;w>>=1)cnt[w]=0;
}
void maxs(i64&a,i64 b){if(a<b)a=b;}
i64 que(int w,pos p){
    if(!cnt[w])return std::max(que(w<<1,p),que(w<<1^1,p));
    pos*a=tr[w];
    int L=0,R=cnt[w]-1,M;
    while(R-L>5)(M=L+R>>1,p*a[M]>p*a[M+1])?(R=M):(L=M+1);
    i64 v=p*a[L++];
    while(L<=R)maxs(v,p*a[L++]);
    return v;
}
int query(){
    i64 ans=-(1ll<<61);
    int l=_(),r=_(),x=_(),y=_();
    pos p=(pos){x,y};
    for(l+=mx-1,r+=mx+1;r-l!=1;l>>=1,r>>=1){
        if(~l&1)maxs(ans,que(l+1,p));
        if(r&1)maxs(ans,que(r-1,p));
    }
    x=ans%P;
    return x<0?x+P:x;
}
int main(){
    _();
    for(int m,sum;sum=now=0,m=_();printf("%u\n",sum)){
        for(int l=mx,r=mx+std::min(300005,m),dep=0;l;l>>=1,r>>=1,++dep){
            for(int i=l;i<=r;++i)tr[i]=ps[dep]+(i-l<<dep),cnt[i]=0;
        }
        for(int w=mx;w;w>>=1)cnt[w]=cnt[w-1]=-1;
        for(;m;--m){
            int o=_();
            if(o==1)push();
            else if(o==2)pop();
            else sum^=query();
        }
    }
    return 0;
}

 

posted on 2017-09-21 09:34  nul  阅读(284)  评论(0编辑  收藏  举报