[Heoi2013]Segment

来源:互联网 发布:知乎 十号胖狐狸 编辑:程序博客网 时间:2024/05/01 02:22

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)
和((x1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段。
其中lastans为上一次询问的答案。初始时lastans=0。
1 ≤ n ≤ 10^5 , 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。

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

标记永久化,不过这题插入的是一条条线段,其实也没什么关系,稍微判断下就好了。不过需要记得判断斜率无穷大,然后基本上就没啥了。

一道比这题简单点的题,[JSOI2008]Blue Mary开公司

两题基本相似,小细节自己画个图理解下就好

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define inf 0x7f7f7f7fusing namespace std;typedef long long ll;typedef unsigned int ui;typedef unsigned long long ull;inline int read(){    int x=0,f=1;char ch=getchar();    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';    return x*f;}inline void print(int x){    if (x>=10)     print(x/10);    putchar(x%10+'0');}const int N=1e5,px=39989,py=1e9;double K[N+10],B[N+10];int n,lastans,cnt;bool check(int x,int y,int pos){    if (!x) return 1;    double l1=K[x]*pos+B[x],l2=K[y]*pos+B[y];    return l1!=l2?l1<l2:x<y;}struct Segment{    #define ls (p<<1)    #define rs (p<<1|1)    int tree[N*4+10];    void insert(int p,int l,int r,int t){//判断和“Blue Mary开公司”稍有不同,不过读者们可以画个图,便可以马上理解了        if (!tree[p])   tree[p]=t;        if (check(tree[p],t,l)) swap(tree[p],t);        if (l==r||K[tree[p]]==K[t]) return;        double g=1.0*(B[tree[p]]-B[t])/(K[t]-K[tree[p]]);        if (g<l||g>r)   return;        int mid=(l+r)>>1;        if (g<=mid) insert(ls,l,mid,tree[p]),tree[p]=t;        if (g>mid)  insert(rs,mid+1,r,t);    }    int query(int p,int l,int r,int t){        if (l==r)   return tree[p];        int mid=(l+r)>>1,ans;        if (t<=mid) ans=query(ls,l,mid,t);        if (t>mid)  ans=query(rs,mid+1,r,t);        return check(tree[p],ans,t)?ans:tree[p];    }}Tree;void change(int p,int l,int r,int x,int y,int t){//由外部修改转移到线段树上修改    if (x<=l&&r<=y){Tree.insert(p,l,r,t);return;}    int mid=(l+r)>>1;    if (x<=mid) change(p<<1,l,mid,x,y,t);    if (y>mid)  change(p<<1|1,mid+1,r,x,y,t);}int main(){    n=read(),lastans=0;    for (int i=1;i<=n;i++){        int t=read();        if (t){            cnt++;            int x1=read(),y1=read(),x2=read(),y2=read();            x1=(x1+lastans-1)%px+1,y1=(y1+lastans-1)%py+1;            x2=(x2+lastans-1)%px+1,y2=(y2+lastans-1)%py+1;            if (x1>x2)  swap(x1,x2),swap(y1,y2);            if (x1==x2) K[cnt]=0,B[cnt]=max(y1,y2);            else{                K[cnt]=1.0*(y2-y1)/(x2-x1);                B[cnt]=1.0*y1-K[cnt]*x1;            }            change(1,1,N,x1,x2,cnt);        }else{            int x=(read()+lastans-1)%px+1;            lastans=Tree.query(1,1,N,x);            printf("%d\n",lastans);        }    }    return 0;}
原创粉丝点击