[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\n",ans[i]);
42     return 0;
43 }

 

posted @ 2018-04-04 10:18  HocRiser  阅读(361)  评论(0编辑  收藏  举报