zoukankan      html  css  js  c++  java
  • [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)
    和((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 0x7f7f7f7f
    using 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
    ",lastans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Selector空轮询处理(转载)
    使用SHOW binlog events查看binlog内容
    netty 3.x 实现http server和遇到的坑
    Tomcat7启动分析(三)Digester的使用(转载)
    MySQL · 引擎特性 · 基于InnoDB的物理复制实现(转载)
    InnoDB多版本(MVCC)实现简要分析(转载)
    MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转载)
    第 4 章 序列和字符串
    BLAST在Windows系统中本地化
    Sublime text3 创建html模板
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/8414537.html
Copyright © 2011-2022 走看看