• 计算几何学习6


    周末搞完了扫描线的部分

    上次说的半平面交问题做法是没问题的

    是按照中垂线划分平面 再求核的面积

    因为是每加入一个直线就判断 所以n^2的好一点

    扫描线板子(poj1177 周长并)

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    #define lc(x) (x << 1)
    #define rc(x) (x << 1 | 1)
    using namespace std;
    const int inf = 0x3fffffff;
    typedef long long LL;
    const int N = 100100;
    struct SegmentTree{
        int cov, sum;
        int ll, rr, cnt;
    }T[N << 2];
    
    struct Lin{
        int x, y1, y2, d;
        bool operator < (const Lin & a) const{
            if(x == a.x) return d > a.d;
            return x < a.x;
        }
    }l[N << 1];
    
    int ax[N << 1], ay[N << 1];
    int xlen, ylen, lcnt;
    
    void Build(int x, int l, int r){
        T[x].sum = T[x].ll = T[x].rr = T[x].cnt = 0;
        if(l == r) return;
        int mid = l + r >> 1;
        Build(lc(x), l, mid);
        Build(rc(x), mid + 1, r);
        return;
    }
    
    void Update(int x, int l, int r){
        if(T[x].cov){
            T[x].ll = T[x].rr = 1;
            T[x].cnt = 1;
            T[x].sum = ay[r + 1] - ay[l];
            return;
        }
        else if(l == r) T[x].ll = T[x].rr = T[x].sum = T[x].cnt = 0;
        else{
            T[x].rr = T[rc(x)].rr;
            T[x].ll = T[lc(x)].ll;
            T[x].sum = T[lc(x)].sum + T[rc(x)].sum;
            T[x].cnt = T[lc(x)].cnt + T[rc(x)].cnt - (T[rc(x)].ll && T[lc(x)].rr);
        }
        return;
    }
    
    void Modify(int x, int l, int r, int L, int R, int d){
        if(L <= l && r <= R){
            T[x].cov += d;
            Update(x, l, r);
            return;
        }
        int mid = l + r >> 1;
        if(L <= mid) Modify(lc(x), l, mid, L, R, d);
        if(R > mid) Modify(rc(x), mid + 1, r, L, R, d);
        Update(x, l, r);
        return;
    }
    
    void Disc(int *a, int &n){
        int nn = 1;
        sort(a + 1, a + n + 1);
        for(int i = 2; i <= n; i ++)
            if(a[i] != a[i - 1]) a[++ nn] = a[i];
        n = nn;
        return;
    }
    
    int n;
    
    LL Abs(LL x){
        if(x < 0) return -x;
        return x; 
    }
    
    void Solve(){
        xlen = 0;
        ylen = 0;
        lcnt = 0;
        scanf("%d", &n);
        int x1, y1, x2, y2;
        for(int i = 1; i <= n; i ++){
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            l[++ lcnt] = (Lin) {x1, y1, y2, 1};
            l[++ lcnt] = (Lin) {x2, y1, y2, -1};
            ax[++ xlen] = x1;
            ay[++ ylen] = y1;
            ax[++ xlen] = x2;
            ay[++ ylen] = y2;        
        }
        
        Disc(ax, xlen);
        Disc(ay, ylen);
        Build(1, 1, ylen - 1);
        
        for(int i = 1; i <= lcnt; i ++){
            l[i].x = lower_bound(ax + 1, ax + xlen + 1, l[i].x) - ax;
            l[i].y1 = lower_bound(ay + 1, ay + ylen + 1, l[i].y1) - ay;
            l[i].y2 = lower_bound(ay + 1, ay + ylen + 1, l[i].y2) - ay;
        }
        
        sort(l + 1, l + lcnt + 1);
        int j = 1;
        LL ans = 0, lastans = 0;
        
        for(int i = 1; i <= lcnt; i ++){
            Modify(1, 1, ylen - 1, l[i].y1, l[i].y2 - 1, l[i].d);
            ans += abs(T[1].sum - lastans) + 2 * T[1].cnt * (ax[l[i + 1].x] - ax[l[i].x]);
            lastans = T[1].sum;
        }
        
        printf("%lld\n", ans);
        
        return;
    }
    
    int main(){
        Solve();
        return 0;
    }
    View Code

    这是改进之后的写法了= =

    poj 1177有个地方查了很久

    就是统计答案的时候 是每加一条线段 都要统计一下 而不是我以前按照离散后的x坐标来求

    因为求周长并时两次y轴长度相减得到的当前线段 对合并后周长的贡献 而如果按照x坐标求 就会在y轴部分漏掉一些

    还有一个地方就是对于相同的x 先加入线段 再删除线段

    举个例子就是

    如果按照x来考虑 y轴贡献是 3 + 1 + 4 = 8

    中间的1是 4 - 3 第二个边长减第一个 是无意义的

    而如果按照线段来考虑结果是 3 + 2 + 1 + 4 = 10

    2是第二个左侧加入后的贡献 1是第一个右侧的贡献

    x轴部分就统计线段树中的区间个数就行了

    或者再按x轴做一遍线段树也可以

    面积并比这个简单 按x离散后的值处理也可以 少维护了区间个数的信息

    其余一样

    poj 1151 poj 1389 poj1177都是板子题

    poj 3695 数据很奇怪

    矩形个数n很小 查询m很多

    感觉 m * nlogn可以过 但是被卡掉了

    网上说的容斥感觉是 m * 2 ^ n 感觉很不靠谱= =但是可以过

    我写的是一种 m * n ^ 2的做法

    把坐标离散后可以得到 40 * 40个面积块

    由于只有20个矩形 每个面积块被覆盖的信息可以由一个正数表示

    在询问时扫所有块 和询问&一下 统计出结果

    poj 3565

    n个a类点 n个b类点

    寻找一种ab一一对应的关系 使得所有线段不相交

    我就是刚开始随便给一种连边方式 做n次调整

    每次像冒泡一样检查 就好了

    poj 2002

    给你一些点 n <= 1000

    问能组成多少个正方形

    枚举一条边 set里找一下就好

    昨天的I题

    按照 从小到大 可以推出 f(2 * n + 1) = f(n) * 4 + 2 * n + 2

    从大到小可以推出 f(2 * n) = 2 * (f(n) + f(n - 1))

    之后就是大整数的问题了

    跟着ytz学习了一点java

    在智深指导下写了一发java的I

    一会贴出来 当做大整数板子吧

    import java.util.*;
    import java.math.*;
    
    public class Main{
        static HashMap <BigInteger, BigInteger> f = new HashMap <BigInteger, BigInteger> ();     
        static BigInteger a0 = new BigInteger("0"), a2 = new BigInteger("2"), a1 = new BigInteger("1"), a4 = new BigInteger("4");
            
        static void DFS(BigInteger a){
            BigInteger tmp = f.get(a);
            if(tmp != null) return;
            if(a.mod(a2).compareTo(a0) == 0){
                tmp = a.divide(a2); 
                DFS(tmp);
                DFS(tmp.subtract(a1));
                tmp = (f.get(tmp).add(f.get(tmp.subtract(a1)))).multiply(a2);
                f.put(a, tmp);
                return;
            }
            else{
                tmp = a.divide(a2);
                DFS(tmp);
                tmp = f.get(tmp).multiply(a4).add(a).add(a1);
                f.put(a, tmp);
                return;
            }
        } 
    
        public static void main(String []args){
            Scanner cin = new Scanner (System.in);
            BigInteger n = new BigInteger("0");
            f.put(a0, a0);
            f.put(a1, a2);
            while(cin.hasNext()){
                n = cin.nextBigInteger();
                DFS(n);
                System.out.println(f.get(n).subtract(n.multiply(a2)));
            }
            System.exit(0);
        }
    }
    View Code

    感觉java 还是要学习一个的

    接下来准备开一些解析几何的题

    和固定算法的题了

  • 相关阅读:
    js提交表单错误:document.form.submit() is not a function
    eclipse中把多个项目放在一个work set下
    SpringMVC源码分析系列
    java.util.ConcurrentModificationException详解
    java动态代理(JDK和cglib)代码完整版本
    java静态代理和动态代理
    看完这5张图!不同类型停车位的停车技巧get!
    记住这6个方法,让你的车辆轻松过年检!
    B样条 理论基础
    virtual studio 主题更换
  • 原文地址:https://www.cnblogs.com/drzdk/p/7226077.html
Copyright © 2020-2023  润新知