zoukankan      html  css  js  c++  java
  • BZOJ3165: [Heoi2013]Segment

    3165: [Heoi2013]Segment

    Time Limit: 40 Sec Memory Limit: 256 MB
    Submit: 939 Solved: 387
    [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

    题解

    李超线段树模板题。

    李超线段树的思想大概是这样,每个节点都保留一个能够覆盖这个区间的线段,保证这个线段与区间内任何一个线段比较,都至少一半高于区间内的线段

    对于新来的线段,如果线段包含区间,如果全部高于/低于区间内线段,就覆盖/不覆盖,否则按照交点分类递归下去。
    如果交点在左边,那就递归左边,
    交点在右边,就递归右边。
    最多(log n)
    至于当前节点保留原线段还是新来的线段,按照“保证这个线段与区间内任何一个线段比较,都至少一半高于区间内的线段”规则判断。

    线段不包含区间那就像普通sgt一样递归即可,最多(log n)
    复杂度(O(nlog ^1 n))

    注意线段垂直于x轴时,看做一个点即可。

    要求输出编号最小的,通过修改和查询双重保证编号最小

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <cmath>
    #define Pair std::pair<double, int>
    inline void swap(int &x, int &y){int tmp = x;x = y;y = tmp;}
    inline void read(int &x)
    {
        x = 0;char ch = getchar(), c = ch;
        while(ch < '0' || ch > '9') c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
        if(c == '-') x = -x;
    }
    const int INF = 0x3f3f3f3f;
    const int MAXN = 100000 + 10;
    int max(int a, int b){return a > b ? a : b;}
    double max(double a, double b){return a > b ? a : b;}
    struct Line
    {
    	double k, b;
    	int l, r, rank;
    	Line()
    	{
    		l = 1, r = 40000;
    		rank = k = b = 0;
    	}
    	Line(int x1, int y1, int x2, int y2, int _rank)
    	{
    		rank = _rank;
    		if(x1 > x2) swap(x1, x2), swap(y1, y2);
    		l = x1, r = x2;
    		if(x1 == x2)
    		{
    			k = 0;
    			b = max(y1, y2);	
    		}
    		else
    		{
    			k = ((double)y1 - y2) / (x1 - x2);
    			b = (double)y1 - x1 * k;
    		}
    	}
    	double f(int x)
    	{
    		return k * x + b;
    	}
    };
    struct Node
    {
    	int l, r;
    	Line line;
    }node[MAXN << 2];
    void build(int o = 1, int l = 1, int r = 40000)
    {
    	node[o].l = l, node[o].r = r;
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	build(o << 1, l, mid);
    	build(o << 1 | 1, mid + 1, r);
    }
    void modify(Line L, int o = 1)
    {
    	if(L.l <= node[o].l && node[o].r <= L.r)
    	{
    		if(L.f(node[o].l) <= node[o].line.f(node[o].l) &&
    			L.f(node[o].r) <= node[o].line.f(node[o].r)) return;
    		if(L.f(node[o].l) > node[o].line.f(node[o].l) &&
    			L.f(node[o].r) > node[o].line.f(node[o].r)) 
    			{
    				node[o].line = L;return;
    			}
    		double x = (node[o].line.b - L.b) / (L.k - node[o].line.k);
    		int mid = (node[o].l + node[o].r) >> 1;
    		if(x < mid)
    		{
    			if(L.f(node[o].r) > node[o].line.f(node[o].r))
    				modify(node[o].line, o << 1), node[o].line = L;
    			else modify(L, o << 1);
    		}
    		else
    		{
    			if(L.f(node[o].l) > node[o].line.f(node[o].l))
    				modify(node[o].line, o << 1 | 1), node[o].line = L;
    			else modify(L, o << 1 | 1);
    		}
    		return;
    	}
    	int mid = (node[o].l + node[o].r) >> 1;
    	if(L.l <= mid) modify(L, o << 1);
    	if(L.r > mid) modify(L, o << 1 | 1);
    }
    Pair max(Pair a, Pair b)
    {
    	return a.first == b.first ? (b.second < a.second ? b : a) : (a.first < b.first ? b : a);
    }
    Pair ask(int pos, int o = 1)
    {
    	if(node[o].l == node[o].r)
    		return std::make_pair(node[o].line.f(pos), node[o].line.rank);
    	Pair re = std::make_pair(node[o].line.f(pos), node[o].line.rank);
    	int mid = (node[o].l + node[o].r) >> 1;
    	if(pos <= mid) re = max(re, ask(pos, o << 1));
    	else re = max(re, ask(pos, o << 1 | 1));
    	return re;
    }
    int tot;
    int main()
    {
    	int lastans = 0, n;
    	read(n);
    	build();
    	for(int i = 1;i <= n;++ i)
    	{
    		int tmp;read(tmp);
    		if(tmp)
    		{
    			int tmp1, tmp2, tmp3, tmp4;
    			read(tmp1), read(tmp2), read(tmp3), read(tmp4);
    			tmp1 = (tmp1 + lastans - 1) % 39989 + 1;
    			tmp2 = (tmp2 + lastans - 1) % 1000000000 + 1;
    			tmp3 = (tmp3 + lastans - 1) % 39989 + 1;
    			tmp4 = (tmp4 + lastans - 1) % 1000000000 + 1;
    			modify(Line(tmp1, tmp2, tmp3, tmp4, ++ tot));
    		}
    		else
    		{
    			read(tmp);
    			tmp = (tmp + lastans - 1) % 39989 + 1;
    			printf("%d
    ", lastans = ask(tmp).second);
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    『ORACLE』 DBLINK(11g)
    『ORACLE』 对永久表空间进行DDL操作(11g)
    『ORACLE』 对永久表空间进行DML操作(11g)
    『ORACLE』 数据库suspend模式(11g)
    『ORACLE』 数据库quiesce模式(11g)
    『ORACLE』 数据库restricted模式(11g)
    [转]为什么不去读顶级会议上的论文
    learn from 德国老师
    IDA 调试 Android
    L#中 int.TryParse 有问题
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8574153.html
Copyright © 2011-2022 走看看