• 【uoj#191.】Unknown


    论文题,手残+脑残根本写不出来点分写法。

    论文里5.14好像有个优雅的写法。

    考虑用线段树维护凸包,1操作就是往线段树最底层加点,每把一根线段加满就合并。这样显然是不行的,只要在一个点左右横跳就会t。

    然后考虑每次不立即合并,而是等到下一次同层的线段需要合并的时候再进行合并,这样不管怎么搞都是nlog2n。具体势能分析不会,所以就简单证一下。

    插入&删除时,考虑合并一条长度为L的线段,至少要进行L次插入,平均下来对每层的贡献就是O(1),共logn层,所以每次的复杂度是logn的,总复杂度nlogn

    查询时,考虑一个区间会被分成log条线段,考虑每条线段的情况:

    1、已经被合并

    2、没有被合并,两个子区间已经合并。

    3、没有被合并,左子区间已经被合并。

    由于只会在右端插入,所以左区间肯定比右区间先合并,所以最坏情况下只需要递归右区间。

    1、2都是O(1)直接求,3需要递归,共log层,单次查询复杂度log2n,总复杂度nlog2n。

    uoj上好像并没有把空间卡到64M;

    #include<bits/stdc++.h>
    #define maxn 5000005
    #define ll long long
    #define INF 1ll<<62
    #define MOD 998244353
    
    using namespace std;
    
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int n=524288;
    
    struct P{
        int x,y;
        P(int x,int y):x(x),y(y){};
        P(){};
        bool operator < (const P &tmp)const{if(x==tmp.x)return y<tmp.y;return x<tmp.x;}
    }pool[maxn],*tt,*a[n<<1];
    
    ll Cross(P a,P b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
    
    inline int calc(P a,P b,P c){
        int up1=b.y-a.y,up2=c.y-b.y;
        int down1=b.x-a.x,down2=c.x-b.x;
        return 1ll*up1*down2<=1ll*up2*down1;
    }
    
    inline int calc2(P a,P b,P c){
        int up1=b.y-a.y,up2=c.y;
        int down1=b.x-a.x,down2=c.x;
        return 1ll*up1*down2>=1ll*up2*down1;
    }
    
    inline void push(P *a,int &ta,P p){
        while(ta>1&&calc(a[ta-1],a[ta],p))--ta;
        a[++ta]=p;
    }
    
    int TOT;
    
    inline void merge(P *&a,int &ta,P *b,int tb,P *c,int tc){
        a=tt;ta=0;
        int t1=1,t2=1;
        while(t1<=tb||t2<=tc){
            if(t1<=tb){
                if(t2>tc||b[t1]<c[t2])push(a,ta,b[t1++]);
                else push(a,ta,c[t2++]);
            }else push(a,ta,c[t2++]);
        }
        tt+=ta;
    }
    
    int tot[maxn],last[maxn];
    
    inline void insert(int o,int l,int r,int x,int dep,P v){
        if(l==r){
            a[o]=tt++;tt->x=v.x;tt->y=v.y;tot[o]=1;
            return;
        }
        int mid=l+r>>1;
        if(x<=mid)insert(o<<1,l,mid,x,dep+1,v);
        else insert(o<<1|1,mid+1,r,x,dep+1,v);
        if(x==r){
            if(last[dep]){
                int t=last[dep];
                merge(a[t],tot[t],a[t<<1],tot[t<<1],a[t<<1|1],tot[t<<1|1]);
            }
            last[dep]=o;
        }
    }
    
    inline void erase(int o,int l,int r,int x,int dep){
        tot[o]=0;
        if(l==r)return;
        if(last[dep]==o)last[dep]=0;
        int mid=l+r>>1;
        if(x<=mid)erase(o<<1,l,mid,x,dep+1);
        else erase(o<<1|1,mid+1,r,x,dep+1);
    }
    
    inline ll query(P *a,int tot,P p){
        int l=1,r=tot;
        while(l<=r){
            int mid=l+r>>1;
            if(mid==tot)return Cross(p,a[mid]);
            if(calc2(a[mid],a[mid+1],p))l=mid+1;
            else r=mid-1;
        }
        return Cross(p,a[l]);
    }
    
    ll Max;
    
    inline void query(int o,int l,int r,int x,int y,P v){
        if(tot[o]&&x<=l&&r<=y){
            Max=max(Max,query(a[o],tot[o],v));
            return;
        }
        int mid=l+r>>1;
        if(x<=mid)query(o<<1,l,mid,x,y,v);
        if(y>mid)query(o<<1|1,mid+1,r,x,y,v);
    }
    
    int m,Ans;
    
    void WoRk(){
        int type,f1,f2,f3,f4;
        for(int i=1;i<=m;++i){
            type=read();
            if(type==1){
                f1=read();f2=read();
                insert(1,1,n,++TOT,1,P(f1,f2));
            }else
            if(type==2){
                erase(1,1,n,TOT--,1);
            }else{
                f1=read();f2=read();f3=read();f4=read();
                Max=-INF;query(1,1,n,f1,f2,P(f3,f4));
                Ans^=(Max%MOD+MOD)%MOD;
            }
        }
        printf("%d
    ",Ans);
    }
    
    void Init(){
        tt=pool;TOT=Ans=0;
        memset(last,0,sizeof(last));
        memset(tot,0,sizeof(tot));
    }
    
    int main(){
        int Illyasviel_Von_Einzbern=read();
        for(;;){
            m=read();
            if(m==0)return 0;
            Init();
            WoRk();
        }
        return 0;
    }
  • 相关阅读:
    java虚拟机之类加载机制
    java虚拟机之垃圾收集器
    java虚拟机之内存模型
    java基础之NIO
    java基础之字符串
    Integer.valueOf源码分析
    将博客搬至CSDN
    url中向后台传递参数中文乱码
    Layui主窗口和Iframe层参数传递
    百度地图Api 加载海量点
  • 原文地址:https://www.cnblogs.com/illya/p/7698111.html
Copyright © 2020-2023  润新知