[bzoj3165] [HEOI2013]Segment

Description

要求在平面直角坐标系下维护两个操作:
1.在平面上加入一条线段。记第i条被插入的线段的标号为i。
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。

Input

第一行一个整数n,表示共n 个操作。
接下来n行,每行第一个数为0或1。
若该数为 0,则后面跟着一个正整数 k,表示询问与直线
x = ((k +lastans–1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段y坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号。
若该数为 1,则后面跟着四个正整数 x0, y0, x 1, y 1,表示插入一条两个端点为
((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段。
其中lastans为上一次询问的答案。初始时lastans=0。

Output

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

Sample Input

6 
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5

Sample Output

2 
0 3 

Solution

李超线段树。

线段树每个区间记录一条最优线段。

对于一条线段,以及一条新加的线段,分类讨论:

  • 若新线段和旧线段没有交点,更新之后直接退出就好了。
  • 否则考虑交点和\(mid\)的位置关系,一边直接覆盖,另一边递归处理。

对于每次操作,一共会拆成\(O(\log n)\)个区间,每个区间花费\(O(\log n)\)的代价更新,总复杂度\(O(m\log^2n)\)

#include<bits/stdc++.h>
using namespace std;
 
void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

const int maxn = 5e5+10;
const int N = 4e4;

struct data {
	int x,y,xx,yy,id;
	double k,b;    
	double calc(int a) {return k*a+b;}
	void lm(int a) {y=calc(a),x=a;}
	void rm(int a) {yy=calc(a),xx=a;}
};

int judge(data a,data b,int x) {
	if(!a.id) return 1;
	return a.calc(x)==b.calc(x)?a.id>b.id:a.calc(x)<b.calc(x);
}

int cnt;

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct Segment_Tree {
	data t[maxn<<2];
	void update(int p,int l,int r,data s) {
		if(s.x<l) s.lm(l);
		if(s.xx>r) s.rm(r);
		if(judge(t[p],s,mid)) swap(s,t[p]);
		if(l==r) return ;
		if(max(s.y,s.yy)<=min(t[p].y,t[p].yy)) return ;
		if(s.k>t[p].k) update(rs,mid+1,r,s);
		else update(ls,l,mid,s);
	}
	void modify(int p,int l,int r,data s) {
		if(s.x<l) s.lm(l);
		if(s.xx>r) s.rm(r);
		if(s.x==l&&s.xx==r) return update(p,l,r,s),void();
		if(s.x<=mid) modify(ls,l,mid,s);
		if(s.xx>mid) modify(rs,mid+1,r,s);
	}
	data query(int p,int l,int r,int x) {
		if(l==r) return t[p];
		data ans=t[p],res;
		if(x<=mid) res=query(ls,l,mid,x);
		else res=query(rs,mid+1,r,x);
		if(judge(ans,res,x)) ans=res;
		return ans;
	}
}SGT;

int main() {
	int t;read(t);
	int lastans=0,id=0;
	data s;
	while(t--) {
		int op,x,y,xx,yy;read(op);
		if(op==1) {
			read(x),read(y),read(xx),read(yy);
			x=(x+lastans-1)%39989+1;
			y=(y+lastans-1)%1000000000+1;
			xx=(xx+lastans-1)%39989+1;
			yy=(yy+lastans-1)%1000000000+1;
			if(x>xx) swap(x,xx),swap(y,yy);
			if(x==xx) {
				y=max(y,yy);
				s=(data){x,y,xx,y,++id,0,1.0*y};
			} else {
				double k=(double)(y-yy)/(1.0*(x-xx));
				s=(data){x,y,xx,yy,++id,k,1.0*y-1.0*x*k};
			}
			SGT.modify(1,1,N,s);
		} else {
			read(x);x=(x+lastans-1)%39989+1;
			write(lastans=SGT.query(1,1,N,x).id);
		}
	}
	return 0;
}
posted @ 2019-01-10 19:04  Hyscere  阅读(229)  评论(0编辑  收藏  举报