zoukankan      html  css  js  c++  java
  • 洛谷P4097 [HEOI2013]Segment(李超线段树)

    题面

    传送门

    题解

    调得咱自闭了……

    不难发现这就是个李超线段树,不过因为这里加入的是线段而不是直线,所以得把线段在线段树上对应区间内拆开之后再执行李超线段树的操作,那么复杂度就是(O(nlog^2n))

    以上是题解,以下是吐(zang)槽(hua)

    为什么我插入竖直线段的时候会出现(l=r)(l imes k+b eq r imes k+b)的情况呢……为什么我本地测会突然(RE)加了个(puts("qwq"))就能输出了呢……

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int M=39989,L=1e9,N=1e5+5;
    struct node{
    	node *lc,*rc;double b,k;bool flag;int id;
    	inline void ins(R double bb,R double kk,R int ii){b=bb,k=kk,id=ii,flag=1;}
    	inline double calc(const R int &x){return k*x+b;}
    }pool[N<<2],*rt;int tot;
    int n,q,id,ii,ql,qr,res,x;double b,k,bb,kk,mx;
    inline node *newnode(){return &pool[tot++];}
    void build(node* &p,int l,int r){
    	p=newnode();if(l==r)return;
    	int mid=(l+r)>>1;
    	build(p->lc,l,mid),build(p->rc,mid+1,r);
    }
    void update(node *p,int l,int r,double b,double k,int id){
    	if(ql<=l&&qr>=r){
    		if(!p->flag)return p->ins(b,k,id),void();
    		double lv1=l*k+b,rv1=r*k+b,lv2=p->calc(l),rv2=p->calc(r);
    		if(lv1<=lv2&&rv1<=rv2)return;
    		if(lv1>lv2&&rv1>rv2)return p->ins(b,k,id),void();
    		int mid=(l+r)>>1;
    		double x=(b-p->b)/(p->k-k);
    		if(lv1<=lv2){
    			if(x<=mid)bb=p->b,kk=p->k,ii=p->id,p->ins(b,k,id),update(p->lc,l,mid,bb,kk,ii);
    			else update(p->rc,mid+1,r,b,k,id);
    		}else{
    			if(x<=mid)update(p->lc,l,mid,b,k,id);
    			else bb=p->b,kk=p->k,ii=p->id,p->ins(b,k,id),update(p->rc,mid+1,r,bb,kk,ii);
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid)update(p->lc,l,mid,b,k,id);
    	if(qr>mid)update(p->rc,mid+1,r,b,k,id);
    }
    void query(node *p,int l,int r){
    	if(cmax(mx,p->calc(x)))res=p->id;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	x<=mid?query(p->lc,l,mid):query(p->rc,mid+1,r);
    }
    int cnt,op,val[N],ID[N];
    int main(){
    	q=read(),n=39989;
    	build(rt,1,n);
    	while(q--){
    		op=read();
    		if(op==1){
    			int x0=(read()+res-1)%n+1,y0=(read()+res-1)%L+1;
    			int x1=(read()+res-1)%n+1,y1=(read()+res-1)%L+1;
    			++cnt;
    			if(x0==x1&&cmax(val[x0],max(y0,y1))){ID[x0]=cnt;continue;}
    			if(x0>x1)swap(x0,x1),swap(y0,y1);
    			k=1.0*(y1-y0)/(x1-x0),b=y0-k*x0,id=cnt,ql=x0,qr=x1;
    			update(rt,1,n,b,k,id);
    		}else{
    			x=(read()+res-1)%n+1,mx=res=0;
    			query(rt,1,n);
    			cmax(mx,1.0*val[x])?res=ID[x]:0;
    			print(res);
    		}
    	}
    	return Ot(),0;
    }
    
  • 相关阅读:
    某一字段分组取最大(小)值所在行的数据
    【JVM】01虚拟机内存模型
    POJ 1845 Sumdiv (求某个数的所有正因子的和)
    POJ 2992 Divisors (求因子个数)
    POJ 3696 The Luckiest number (欧拉函数,好题)
    POJ 1811 Prime Test (Pollard rho 大整数分解)
    POJ 2429 GCD & LCM Inverse (Pollard rho整数分解+dfs枚举)
    POJ 1305 Fermat vs. Pythagoras (毕达哥拉斯三元组)
    POJ 2142 The Balance (解不定方程,找最小值)
    POJ 1006 Biorhythms (中国剩余定理)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10621349.html
Copyright © 2011-2022 走看看