• [BZOJ4822][CQOI2017]老C的任务(扫描线+树状数组)


    4822: [Cqoi2017]老C的任务

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 379  Solved: 203
    [Submit][Status][Discuss]

    Description

    老 C 是个程序员。    
    最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统。作为经验丰富的程序员,老 C 轻松
    地完成了系统的大部分功能,并把其中一个功能交给你来实现。由于一个基站的面积相对于整个城市面积来说非常
    的小,因此每个的基站都可以看作坐标系中的一个点,其位置可以用坐标(x, y)来表示。此外,每个基站还有很多属
    性,例如高度、功率等。运营商经常会划定一个区域,并查询区域中所有基站的信息。现在你需要实现的功能就是,
    对于一个给定的矩形区域,回答该区域中(包括区域边界上的)所有基站的功率总和。如果区域中没有任何基站,则回
    答 0。

    Input

    第一行两个整数 n, m,表示一共有n个基站和m次查询。    
    接下来一共有 n 行,每行由x_i , y_i , p_i 三个空格隔开的整数构成,表示一个基站的坐标(x_i , y_i )和功率p
    _i 。不会有两个基站位于同一坐标。    
    接下来一共有m行,每行由x1_j , y1_j , x2_j , y2_j 四个空格隔开的整数构成,表示一次查询的矩形区域。该矩
    形对角坐标为(x1_j , y1_j )和(x2_j , y2_j ),且 4 边与坐标轴平行。 
    2^31 ≤ x_i , y_i , p_i , x1_j , y1_j , x2_j , y2_j < 2^31, x1_j ≤ x2_j, y1_j ≤ y2_j。   

    Output

    输出 m 行,每行一个整数,对应每次查询的结果。

    Sample Input

    4 2
    0 0 1
    0 1 2
    2 2 4
    1 0 8
    0 0 1 1
    1 1 5 6

    Sample Output

    11
    4

    HINT

    Source

    [Submit][Status][Discuss]

    第一眼离散化+二维树状数组,但是显然空间开不下。

    那么直接把每个矩形拆成两条边,离线后扫描线+树状数组就好了。

    感觉对于区间问题比较常用的几个:主席树,扫描线,CDQ分治,莫队。

    没排序调了半天。。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 #define find(x) lower_bound(b+1,b+tot+1,x)-b
     5 typedef long long ll;
     6 using namespace std;
     7 
     8 const int N=100010;
     9 ll p[N],c[N<<3],ans[N];
    10 int n,m,tot,cnt,x[N],y[N],x1[N],y1[N],x2[N],y2[N],b[N<<3];
    11 struct P{ int x,y; ll p; }pt[N<<1];
    12 struct Q{ int x,l,r,pos; }q[N<<1];
    13 bool operator <(P a,P b){ return a.x<b.x; }
    14 bool operator <(Q a,Q b){ return a.x<b.x; }
    15 
    16 void add(int x,ll k){ for (; x<=tot; x+=x&-x) c[x]+=k; }
    17 ll que(int x){ ll res=0; for (; x; x-=x&-x) res+=c[x]; return res; }
    18 
    19 int main(){
    20     freopen("task.in","r",stdin);
    21     freopen("task.out","w",stdout);
    22     scanf("%d%d",&n,&m);
    23     rep(i,1,n) scanf("%d%d%lld",&x[i],&y[i],&p[i]),b[++tot]=x[i],b[++tot]=y[i];
    24     rep(i,1,m){
    25         scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
    26         b[++tot]=x1[i]-1; b[++tot]=y1[i]-1; b[++tot]=x2[i]; b[++tot]=y2[i];
    27     }
    28     sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1;
    29     rep(i,1,n) x[i]=find(x[i]),y[i]=find(y[i]),pt[i]=(P){x[i],y[i],p[i]};
    30     rep(i,1,m){
    31         x1[i]=find(x1[i]-1); y1[i]=find(y1[i]-1);
    32         x2[i]=find(x2[i]); y2[i]=find(y2[i]);
    33         q[++cnt]=(Q){x1[i],y1[i],y2[i],i}; q[++cnt]=(Q){x2[i],y1[i],y2[i],i};
    34     }
    35     sort(pt+1,pt+n+1); sort(q+1,q+cnt+1); int now=1;
    36     rep(i,1,cnt){
    37         while (pt[now].x<=q[i].x && now<=n) add(pt[now].y,pt[now].p),now++;
    38         if (!ans[q[i].pos]) ans[q[i].pos]=que(q[i].r)-que(q[i].l);
    39             else ans[q[i].pos]=que(q[i].r)-que(q[i].l)-ans[q[i].pos];
    40     }
    41     rep(i,1,m) printf("%lld
    ",ans[i]);
    42     return 0;
    43 }
  • 相关阅读:
    迪杰斯特拉算法
    基数排序
    快排算法
    插入排序与希尔排序算法
    java--jmm知识
    Java基础
    socket代理
    TestLink 学习第一周
    软件体系结构第三章之解释器风格
    如何衡量个人在各自团队的效率和绩效
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8715775.html
Copyright © 2020-2023  润新知