• 矩形面积交 [区间树状数组, 扫描线]


    矩形面积交



    color{red}{正解部分}

    每个矩形提出其 左边右边 , 每条边都使用三元组 (l,r,flag,type)(l, r, flag, type)表示, 放置对应的 xx 坐标上,

    使用一条 扫描线 从左向右扫, 如下图计算 橙色询问矩形 的答案,

    计算相交面积 s2s_2 时, 考虑使用 yy 总相交面积 s3s_3 减去 yy 相交 xx 不相交面积 s1s_1 .

    s3s_3 可以在 询问矩形 右边 通过查询 [l,r][l, r] 的面积和得到 .



    使用前面 黄色虚线面积 减去 绿色面积 得到 s1s_1 .

    区间树状数组 :

    • 区间查询: [1,r][1, r], res=i=1rj=1id[j]=i=1r(ri+1)×d[i]=(r+1)i=1rd[i]i=1ri×d[i]res = sumlimits_{i=1}^{r}sumlimits_{j=1}^i d[j] = sumlimits_{i=1}^{r} (r-i+1) imes d[i] = (r+1)sumlimits_{i=1}^{r} d[i] - sumlimits_{i=1}^{r}i imes d[i] .

      于是 维护 d[i]d[i], i×d[i]i imes d[i]

    • 区间修改 (+x)(+x):
      d[i]d[i] 差分, ll+x+x, r+1r+1x-x .
      i×d[i]i imes d[i] 差分, ll+ x×l+ x imes l, r+1r+1 x×(r+1)- x imes (r+1) .


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 5e5 + 5;
    
    int N;
    int M;
    int W;
    int L;
    int cnt;
    
    ll Ans[maxn];
    
    struct Sgment{ int x, l, r, flag, id; } A[maxn<<2];
    
    bool cmp(Sgment a, Sgment b){ return a.x < b.x; }
    
    struct Bit_Tree{
    
            int lim;
            ll d[maxn], d2[maxn];
    
            void Add(int k, ll x){
                    for(reg int i = k; i <= lim; i += (i&-i)) d[i] += x, d2[i] += 1ll*x*k;
            }
    
            ll Ask(int k){
                    if(k <= 0) return 0;
                    ll s = 0;
                    for(reg int i = k; i; i -= (i&-i)) s += (1ll*k+1)*d[i] - d2[i];
                    return s;
            }
    
            void modify(const int &l, const int &r, const ll &x){ Add(l, x), Add(r+1, -x); }
    
            ll query(const int &l, const int &r){ return Ask(r) - Ask(l-1); }
    
    } bit_t[2];
    
    int main(){
            N = read(), M = read(), W = read(), L = read();
            for(reg int i = 1; i <= N; i ++){
                    int x1 = read(), y1 = read(), x2 = read(), y2 = read();
                    A[++ cnt] = (Sgment){ x1, y1+1, y2, 1, 0 };
                    A[++ cnt] = (Sgment){ x2, y1+1, y2, -1, 0 };
            }
            for(reg int i = 1; i <= M; i ++){
                    int x1 = read(), y1 = read(), x2 = read(), y2 = read();
                    A[++ cnt] = (Sgment){ x1, y1+1, y2, -1, i };
                    A[++ cnt] = (Sgment){ x2, y1+1, y2, 1, i };
            }
            bit_t[0].lim = bit_t[1].lim = L;
            std::sort(A+1, A+cnt+1, cmp);
            for(reg int i = 0, j = 1; i <= W; i ++){
                    while(A[j].x == i){
                            if(!A[j].id){
                                    bit_t[1].modify(A[j].l, A[j].r, 1ll*A[j].flag*i);
                                    bit_t[0].modify(A[j].l, A[j].r, A[j].flag);
                            }else{
                                    ll s1 = bit_t[1].query(A[j].l, A[j].r);
                                    ll s2 = bit_t[0].query(A[j].l, A[j].r);
                                    Ans[A[j].id] += 1ll*A[j].flag*(1ll*i*s2 - s1);
                            }
                            j ++;
                    }
            }
            for(reg int i = 1; i <= M; i ++) printf("%lld
    ", Ans[i]);
            return 0;
    }
    
  • 相关阅读:
    .NET System.Web.HttpContext.Current.Request报索引超出数组界限。
    Jq将字符串复制粘贴到剪贴板
    设置VS以管理员身份运行
    http遇到的那些坑,iis上传文件报413错误 asp.net MVC
    百度地图api使用,简单搜索+经纬度定位+自定义消息窗口
    常见的sql server 链接问题------持续更新
    解决电脑不能访问局域网共享,局域网共享中找不到。
    博文图片挂了临时解决办法
    博客声明
    06. redis cluster
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822394.html
Copyright © 2020-2023  润新知