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 6Sample Output
11
4HINT
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 }