【bzoj2422】 Times 前缀和

本来想练一下树状数组的,看到网上某人的blog后点了进来。

第一眼发现不会,出去上了个厕所发现离散化后不是一道简单前缀和题吗。

考虑到每一个人出现且仅出现一次,且出现的时间是在一个连续的区间内。

那么对于一组询问(l,r),当这个人在时刻l前消失,或者再时刻l+r后出现,那么你才会看不到。

那么我们维护一个sum1[i],表示在时刻i及之前,出现过并且已经消失的人的数量。

维护一个sum2[i],表示在时刻i及之后才出现的人的数量。

答案显然是n-sum1[l-1]-sum2[l+r]。

然后就没了,空间记得开够!

 1 #include<bits/stdc++.h>
 2 #define M 200005
 3 using namespace std;
 4 
 5 int c[M*4]={0},cnt=0;
 6 int a[M]={0},b[M]={0},l[M]={0},r[M]={0};
 7 int sum1[M*4]={0},sum2[M*4]={0};
 8 
 9 int main(){
10     int n,m;
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++){
13         scanf("%d%d",a+i,b+i);
14         b[i]+=a[i]-1;
15         c[++cnt]=a[i];
16         c[++cnt]=b[i];
17     }
18     for(int i=1;i<=m;i++){
19         scanf("%d%d",l+i,r+i);
20         r[i]+=l[i]-1;
21         c[++cnt]=l[i];
22         c[++cnt]=r[i];
23     }
24     sort(c+1,c+cnt+1);
25     for(int i=1;i<=n;i++)
26     a[i]=lower_bound(c+1,c+cnt+1,a[i])-c,
27     b[i]=lower_bound(c+1,c+cnt+1,b[i])-c;
28     for(int i=1;i<=m;i++)
29     l[i]=lower_bound(c+1,c+cnt+1,l[i])-c,
30     r[i]=lower_bound(c+1,c+cnt+1,r[i])-c;
31     
32     for(int i=1;i<=n;i++)
33     sum1[b[i]]++,sum2[a[i]]++;
34     for(int i=1;i<=cnt;i++) sum1[i]+=sum1[i-1];
35     for(int i=cnt;i;i--) sum2[i]+=sum2[i+1];
36     
37     for(int i=1;i<=m;i++){
38         printf("%d
",n-sum1[l[i]-1]-sum2[r[i]+1]);
39     }
40 }
原文地址:https://www.cnblogs.com/xiefengze1/p/9902121.html