李超线段树80pts求调

P4097 【模板】李超线段树 / [HEOI2013] Segment

liuziqin @ 2024-10-07 16:48:25

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod1=39989;
const int mod2=1e9;
const int N=40000;
const double eps=1e-9;
struct line{
    double k,b;
};
double kth(double x0,double y0,double x1,double y1){
    if(fabs(x0-x1)<=eps)return 0;
    return (y0-y1)/(x0-x1);
}
double bth(double x0,double y0,double x1,double y1){
    if(fabs(x0-x1)<=eps)return max(y0,y1);
    return y0-x0*kth(x0,y0,x1,y1);
}
double get(double x,double k,double b){
    return k*x+b;
}
struct segtree{
    int sum[N<<2];
    line lazy[N<<2];
    bool used[N<<2];
    int check(int p,int l,int r,double k1,double b1,double k2,double b2){
        if(!used[p])return 1;
        if(l==r){
            if(get(l,k1,b1)-get(l,k2,b2)>eps)return 1;
            else return -1;
        }
        int l1=get(l,k1,b1);
        int r1=get(r,k1,b1);
        int l2=get(l,k2,b2);
        int r2=get(r,k2,b2);
        if(fabs(l1-l2)<=eps&&fabs(r1-r2)<=eps)return -1;
        if(l1-l2>eps&&r1-r2>eps)return 1;
        else if((l1-l2<-eps&&r1-r2>eps)||(l1-l2>eps&&r1-r2<-eps))return 0;
        else if((fabs(l1-l2)<=eps&&r1-r2>eps)||(l1-l2>eps&&fabs(r1-r2)<=eps))return 0;
        else return -1;
    }
    void upd(int p,int l,int r,double k,double b,int id){
        if(check(p,l,r,k,b,lazy[p].k,lazy[p].b)==1){
            lazy[p].k=k;
            lazy[p].b=b;
            sum[p]=id;
            used[p]=1;
            return ;
        }
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(check(p*2,l,mid,k,b,lazy[p].k,lazy[p].b)>=0)upd(p*2,l,mid,k,b,id);
        if(check(p*2+1,mid+1,r,k,b,lazy[p].k,lazy[p].b)>=0)upd(p*2+1,mid+1,r,k,b,id);
    }
    void push_down(int p,int l,int r){
        if(!used[p])return ;
        int mid=(l+r)>>1;
        upd(p*2,l,mid,lazy[p].k,lazy[p].b,sum[p]);
        upd(p*2+1,mid+1,r,lazy[p].k,lazy[p].b,sum[p]);
        lazy[p].k=lazy[p].b=sum[p]=0;
        used[p]=0;
    }
    void add(int p,int l,int r,int x,int y,double k,double b,int id){
        if(l>=x&&r<=y){
            upd(p,l,r,k,b,id);
            return ;
        }
        int mid=(l+r)>>1;
        push_down(p,l,r);
        if(mid>=x)add(p*2,l,mid,x,y,k,b,id);
        if(mid<y)add(p*2+1,mid+1,r,x,y,k,b,id);
    }
    int query(int p,int l,int r,int x){
        if(l==r)return sum[p];
        int mid=(l+r)>>1;
        push_down(p,l,r);
        if(mid>=x)return query(p*2,l,mid,x);
        else return query(p*2+1,mid+1,r,x);
    }
}st;
signed main(){
    int q,lastans=0,n=mod1,cnt=0;
    cin>>q;
    while(q--){
        int op,k,x0,y0,x1,y1;
        cin>>op;
        if(op==0){
            cin>>k;
            k=(k+lastans-1)%mod1+1;
            lastans=st.query(1,1,n,k);
            cout<<lastans<<"\n";
        }
        else {
            cnt++;
            cin>>x0>>y0>>x1>>y1;
            x0=(x0+lastans-1)%mod1+1;
            x1=(x1+lastans-1)%mod1+1;
            y0=(y0+lastans-1)%mod2+1;
            y1=(y1+lastans-1)%mod2+1;
            if(x0>x1){
                swap(x0,x1);
                swap(y0,y1);
            }
            long double k=kth(x0,y0,x1,y1);
            long double b=bth(x0,y0,x1,y1);
            st.add(1,1,n,x0,x1,k,b,cnt);
        }
    }
}

WA on #2 #5 #6 #14 #17


by YWHHDJSer @ 2024-10-07 17:00:36

不知道,但是还是建议检查一下精度问题,开long double试试。


by liuziqin @ 2024-10-07 17:12:17

开了,但结果一样。

#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
const int mod1=39989;
const int mod2=1e9;
const int N=40000;
const double eps=1e-9;
struct line{
    double k,b;
};
double kth(double x0,double y0,double x1,double y1){
    if(fabs(x0-x1)<=eps)return 0;
    return (y0-y1)/(x0-x1);
}
double bth(double x0,double y0,double x1,double y1){
    if(fabs(x0-x1)<=eps)return max(y0,y1);
    return y0-x0*kth(x0,y0,x1,y1);
}
double get(double x,double k,double b){
    return k*x+b;
}
struct segtree{
    int sum[N<<2];
    line lazy[N<<2];
    bool used[N<<2];
    int check(int p,int l,int r,double k1,double b1,double k2,double b2){
        if(!used[p])return 1;
        if(l==r){
            if(get(l,k1,b1)-get(l,k2,b2)>eps)return 1;
            else return -1;
        }
        int l1=get(l,k1,b1);
        int r1=get(r,k1,b1);
        int l2=get(l,k2,b2);
        int r2=get(r,k2,b2);
        if(fabs(l1-l2)<=eps&&fabs(r1-r2)<=eps)return -1;
        if(l1-l2>eps&&r1-r2>eps)return 1;
        else if((l1-l2<-eps&&r1-r2>eps)||(l1-l2>eps&&r1-r2<-eps))return 0;
        else if((fabs(l1-l2)<=eps&&r1-r2>eps)||(l1-l2>eps&&fabs(r1-r2)<=eps))return 0;
        else return -1;
    }
    void upd(int p,int l,int r,double k,double b,int id){
        if(check(p,l,r,k,b,lazy[p].k,lazy[p].b)==1){
            lazy[p].k=k;
            lazy[p].b=b;
            sum[p]=id;
            used[p]=1;
            return ;
        }
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(check(p*2,l,mid,k,b,lazy[p].k,lazy[p].b)>=0)upd(p*2,l,mid,k,b,id);
        if(check(p*2+1,mid+1,r,k,b,lazy[p].k,lazy[p].b)>=0)upd(p*2+1,mid+1,r,k,b,id);
    }
    void push_down(int p,int l,int r){
        if(!used[p])return ;
        int mid=(l+r)>>1;
        upd(p*2,l,mid,lazy[p].k,lazy[p].b,sum[p]);
        upd(p*2+1,mid+1,r,lazy[p].k,lazy[p].b,sum[p]);
        lazy[p].k=lazy[p].b=sum[p]=0;
        used[p]=0;
    }
    void add(int p,int l,int r,int x,int y,double k,double b,int id){
        if(l>=x&&r<=y){
            upd(p,l,r,k,b,id);
            return ;
        }
        int mid=(l+r)>>1;
        push_down(p,l,r);
        if(mid>=x)add(p*2,l,mid,x,y,k,b,id);
        if(mid<y)add(p*2+1,mid+1,r,x,y,k,b,id);
    }
    int query(int p,int l,int r,int x){
        if(l==r)return sum[p];
        int mid=(l+r)>>1;
        push_down(p,l,r);
        if(mid>=x)return query(p*2,l,mid,x);
        else return query(p*2+1,mid+1,r,x);
    }
}st;
signed main(){
    int q,lastans=0,n=mod1,cnt=0;
    cin>>q;
    while(q--){
        int op,k,x0,y0,x1,y1;
        cin>>op;
        if(op==0){
            cin>>k;
            k=(k+lastans-1)%mod1+1;
            lastans=st.query(1,1,n,k);
            cout<<lastans<<"\n";
        }
        else {
            cnt++;
            cin>>x0>>y0>>x1>>y1;
            x0=(x0+lastans-1)%mod1+1;
            x1=(x1+lastans-1)%mod1+1;
            y0=(y0+lastans-1)%mod2+1;
            y1=(y1+lastans-1)%mod2+1;
            if(x0>x1){
                swap(x0,x1);
                swap(y0,y1);
            }
            double k=kth(x0,y0,x1,y1);
            double b=bth(x0,y0,x1,y1);
            st.add(1,1,n,x0,x1,k,b,cnt);
        }
    }
}

by liuziqin @ 2024-10-07 17:12:38

@YWHHDJSer


by YWHHDJSer @ 2024-10-07 17:28:12

看一下是不是upd的锅,感觉是不是分讨的情况少了。一个区间保留的优势线段是在该区间占有一半及以上优势区的线段,所以有时保留有一定缺陷的线段(雾。

总之感觉是upd的问题。


by YWHHDJSer @ 2024-10-07 17:28:22

@liuziqin


by liuziqin @ 2024-10-07 20:17:09

此贴结。

死因:double敲成了int


by wjy2020 @ 2024-10-07 21:14:12

@liuziqin

补充:lazy传递时没有默认传编号最小的线段


|