BZOJ3165: [Heoi2013]Segment

BZOJ3165: [Heoi2013]Segmentphp

並不知道爲何在$BZOJ$上,這是道權限題。。。html

本蒟蒻表示沒錢氪金。。。ios

這裏附上洛谷的題面:post

P4097 [HEOI2013]Segmentui

題目描述

要求在平面直角座標系下維護兩個操做:url

  1. 在平面上加入一條線段。記第 i 條被插入的線段的標號爲 i
  2. 給定一個數 k,詢問與直線 x = k 相交的線段中,交點最靠上的線段的編號。

輸入輸出格式

輸入格式:spa

第一行一個整數 n,表示共 n 個操做htm

接下來 n 行,每行第一個數爲 0 或 1blog

若該數爲 0,則後面跟着一個正整數 k,表示詢問與直線 x = ((k + lastans – 1)%39989+1)相交的線段中交點(包括在端點相交的情形)最靠上的線段的編號,其中%表示取餘。若某條線段爲直線的一部分,則視做直線與線段交於該線段 y 座標最大處。如有多條線段符合要求,輸出編號最小的線段的編號get

若該數爲 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\n",last);
		}
	}
}
void init(){
	n=read();
	buildtree(1,MODX+11,1);
}
int main(){
	init();
	work();
    return 0;
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息