• BZOJ3165: [Heoi2013]Segment


    BZOJ3165: [Heoi2013]Segment

    并不知道为什么在$BZOJ$上,这是道权限题。。。

    本蒟蒻表示没钱氪金。。。

    这里附上洛谷的题面:

    P4097 [HEOI2013]Segment

    题目描述

    要求在平面直角坐标系下维护两个操作:

    1. 在平面上加入一条线段。记第 i 条被插入的线段的标号为 i
    2. 给定一个数 k,询问与直线 x = k 相交的线段中,交点最靠上的线段的编号。

    输入输出格式

    输入格式:

    第一行一个整数 n,表示共 n 个操作

    接下来 n 行,每行第一个数为 0 或 1

    若该数为 0,则后面跟着一个正整数 k,表示询问与直线 x = ((k + lastans – 1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段 y 坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号

    若该数为 1,则后面跟着四个正整数 x0, y0, x1, y1,表示插入一条两个端点为 ((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和 ((x1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段

    其中 lastans 为上一次询问的答案。初始时 lastans=0

    输出格式:

    对于每个 0 操作,输出一行,包含一个正整数,表示交点最靠上的线段的编 号。若不存在与直线相交的线段,答案为 0

    输入输出样例

    输入样例#1: 复制
    6 
    1 8 5 10 8 
    1 6 7 2 6 
    0 2 
    0 9 
    1 4 7 6 7 
    0 5
    输出样例#1: 复制
    2 
    0 
    3

    说明

    对于 30%的数据,n ≤ 1000
    对于 100%的数据,1 ≤ n ≤ 10^5, 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9


    题解Here!

    看到这种题,直接上李超树就好。

    什么?你不知道李超树?

    丢个链接:BZOJ1568: [JSOI2008]Blue Mary开公司

    然后就可以随便跑了。

    注:数据有毒,有某种数据是:$x_0==x_1,y_0!=y_1$

    记得特判一下。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define ID(x) a[x].id
    #define MUL(x) line[a[x].id].k
    #define ADD(x) line[a[x].id].b
    #define SIGN(x) a[x].c
    #define LSIDE(x) a[x].l
    #define RSIDE(x) a[x].r
    #define MAXN 100010
    #define MODX 39989
    #define MODY 1000000000
    using namespace std;
    int n,num_line=0;
    struct Line{
    	double k,b;
    }line[MAXN];
    struct Segment_Tree{
    	int id,l,r;
    	bool c;
    }a[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add_line(double x1,double y1,double x2,double y2){
    	num_line++;
    	if(x1!=x2){
    		line[num_line].k=(y1-y2)/(x1-x2);
    		line[num_line].b=y1-x1*line[num_line].k;
    	}
    	else{
    		line[num_line].k=0;
    		line[num_line].b=max(y1,y2);
    	}
    }
    void buildtree(int l,int r,int rt){
    	LSIDE(rt)=l;RSIDE(rt)=r;ID(rt)=0;SIGN(rt)=false;
    	if(l==r)return;
    	int mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    }
    void change(int id,int rt){
    	if(!SIGN(rt)){
    		SIGN(rt)=true;
    		ID(rt)=id;
    		return;
    	}
    	double l1=MUL(rt)*LSIDE(rt)+ADD(rt),l2=line[id].k*LSIDE(rt)+line[id].b;
    	double r1=MUL(rt)*RSIDE(rt)+ADD(rt),r2=line[id].k*RSIDE(rt)+line[id].b;
    	if(l1>=l2&&r1>=r2)return;
    	else if(l1<l2&&r1<r2){
    		ID(rt)=id;
    		return;
    	}
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	double mid1=MUL(rt)*mid+ADD(rt),mid2=line[id].k*mid+line[id].b;
    	if(l2>=l1){
    		if(mid2<mid1)change(id,LSON);
    		else{
    			change(ID(rt),RSON);
    			ID(rt)=id;
    		}
    	}
    	else{
    		if(mid2<mid1)change(id,RSON);
    		else{
    			change(ID(rt),LSON);
    			ID(rt)=id;
    		}
    	}
    }
    void update(int l,int r,int id,int rt){
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		change(id,rt);
    		return;
    	}
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update(l,r,id,LSON);
    	if(mid<r)update(l,r,id,RSON);
    }
    int query(int l,int r,int rt){
    	int ans=rt;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return rt;
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid){
    		int id=query(l,r,LSON);
    		double now=MUL(ans)*l+ADD(ans),Left=MUL(id)*l+ADD(id);
    		if(now<Left)ans=id;
    		else if(now==Left)ans=min(ans,id);
    	}
    	if(mid<r){
    		int id=query(l,r,RSON);
    		double now=MUL(ans)*l+ADD(ans),Right=MUL(id)*l+ADD(id);
    		if(now<Right)ans=id;
    		else if(now==Right)ans=min(ans,id);
    	}
    	return ans;
    }
    void work(){
    	int last=0,f,x,x1,y1,x2,y2;
    	while(n--){
    		f=read();
    		if(f){
    			x1=(read()+last-1+MODX)%MODX+1;y1=(read()+last-1+MODY)%MODY+1;
    			x2=(read()+last-1+MODX)%MODX+1;y2=(read()+last-1+MODY)%MODY+1;
    			if(x1>x2){swap(x1,x2);swap(y1,y2);}
    			add_line(x1,y1,x2,y2);
    			update(x1,x2,num_line,1);
    		}
    		else{
    			x=(read()+last-1)%MODX+1;
    			last=query(x,x,1);
    			last=ID(last);
    			printf("%d
    ",last);
    		}
    	}
    }
    void init(){
    	n=read();
    	buildtree(1,MODX+11,1);
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    (三)认识twisted reactor
    (二)inlineCallbacks,同步方式写异步代码
    (一)使用twisted Deferred
    javascript通过字典思想操作数据
    锱铢必较,从(function(){}())与(function(){})()说起
    针对谷歌默认最小字体12px的正确解决方案 (css、html)
    百度搜索研发部:同义词反馈机制
    LinkedList与ArrayList的区别
    从源码的角度分析List与Set的区别
    springboot整合redisson分布式锁
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9542964.html
Copyright © 2020-2023  润新知