3165: [Heoi2013]Segment

3165: [Heoi2013]Segment

Time Limit: 40 Sec   Memory Limit: 256 MB
Submit: 428   Solved: 169
[ Submit][ Status][ Discuss]

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

HINT

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

Source

[ Submit][ Status][ Discuss]

李超树,,记得特判斜率正无穷,额
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 4E4 + 10;
const int mo = 39989;
const int mo2 = 1E9;
const int INF = ~0U>>1;
typedef double DB;
const DB eps = 1E-10;

DB Max,k[maxn*20],b[maxn*20];
int n,cnt,lastans,ans,num[maxn*20];

void pushdown(int o,int l,int r,DB K,DB B,int Num)
{
	DB A1 = K*(DB)(l) + B,A2 = k[o]*(DB)(l) + b[o];
	DB B1 = K*(DB)(r) + B,B2 = k[o]*(DB)(r) + b[o];
	if (A1 > A2 && B1 > B2) {k[o] = K; b[o] = B; num[o] = Num; return;}
	if (A1 < A2 && B1 < B2) return;
	if (l == r) return;
	int mid = (l + r) >> 1;
	DB x = (b[o] - B)/(K - k[o]);
	if (x <= mid) {
		if (A1 > A2) pushdown(2*o,l,mid,K,B,Num);
		else pushdown(2*o,l,mid,k[o],b[o],num[o]),k[o] = K,b[o] = B,num[o] = Num;
	}
	else {
		if (A1 > A2) pushdown(2*o+1,mid+1,r,k[o],b[o],num[o]),k[o] = K,b[o] = B,num[o] = Num;
		else pushdown(2*o+1,mid+1,r,K,B,Num);
	}
}

void Insert(int o,int l,int r,int ql,int qr,DB K,DB B,int Num)
{
	if (ql <= l && r <= qr) {pushdown(o,l,r,K,B,Num); return;}
	int mid = (l + r) >> 1;
	if (ql <= mid) Insert(2*o,l,mid,ql,qr,K,B,Num);
	if (qr > mid) Insert(2*o+1,mid+1,r,ql,qr,K,B,Num);
}

void Query(int o,int l,int r,int pos)
{
	DB now = k[o]*(DB)(pos) + b[o];
	if (now - eps > Max) Max = now,ans = num[o];
	else if (fabs(now - Max) <= eps) ans = min(ans,num[o]);
	if (l == r) return;
	int mid = (l + r) >> 1;
	if (pos <= mid) Query(2*o,l,mid,pos);
	else Query(2*o+1,mid+1,r,pos);
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> n;
	while (n--) {
		int typ; scanf("%d",&typ);
		if (!typ) {
			Max = -INF; ans = 0;
			int pos; scanf("%d",&pos);
			pos = (pos + lastans - 1)%mo + 1;
			Query(1,1,maxn,pos);
			lastans = ans;
			printf("%d\n",lastans); 
		}
		else {
			int xl,yl,xr,yr; scanf("%d%d%d%d",&xl,&yl,&xr,&yr);
			xl = (xl + lastans - 1)%mo + 1;
			xr = (xr + lastans - 1)%mo + 1;
			yl = (yl + lastans - 1)%mo2 + 1;
			yr = (yr + lastans - 1)%mo2 + 1;
			if (xl > xr) swap(xl,xr),swap(yl,yr);
			DB K,B;
			if (xl == xr) K = 0; else K = (DB)(yr-yl)/(DB)(xr-xl);
			B = (DB)(yl) - (DB)(xl)*K;
			Insert(1,1,maxn,xl,xr,K,B,++cnt);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值