ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】
1 2098 : Drink coffee 2 时间限制:1 Sec 内存限制:256 MiB 3 提交:40 答案正确:14 4 5 提交 状态 讨论区 6 7 题目描述 8 为了在上课时保持清醒,凯伦需要一些咖啡。咖啡爱好者凯伦想知道最佳的温度来冲煮完美的咖啡。因此,她花了一些时间阅读几本食谱,其中包括广受好评的“咖啡的艺术”。 9 她知道有n个食谱,其中第i个食谱建议应当在li和ri度之间冲煮以达到最佳的味道。凯伦认为如果至少k个食谱推荐某个温度,那么那个温度是可以接受的。 10 凯伦的性格比较多变,因此她会问q个问题,对于每一个问题,她会给出一个温度区间[a,b],你要告诉她有多少可接受的整数温度在这个范围内。 11 12 输入 13 第一行输入包含三个整数,n,k(1≤k≤n≤200000)和q(1≤q≤200000),如题中所描述。 14 接下来n行描述每一个食谱,具体来说,其中的第i行包含两个整数li和ri(1≤li≤ri≤200000),描述第i个食谱建议咖啡在li和ri度之间进行冲煮(包括端值)。 15 接下来q行为q个询问。这些行中的每一行都包含a和b,(1≤a≤b≤200000),表示她想知道a和b度之间的可接受的整数温度的数量,包括a和b。 16 输出 17 对于每个询问,输出一个答案。 18 19 样例输入 20 复制 21 3 2 4 22 91 94 23 92 97 24 97 99 25 92 94 26 93 97 27 95 96 28 90 100 29 样例输出 30 复制 31 3 32 3 33 0 34 4 35 提示
大致思路:
差分 + 二分索引树。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using namespace std; 2 #define inf 0x3f3f3f3f 3 const double pi=acos(-1.0); 4 #define ll long long 5 #define N 200008 6 #define lson root<<1 7 #define rson root<<1|1 8 int a[N];//统计个数 9 int bit[N]; 10 int lowbit(int x){ 11 return x & -x; //或者可以return x&(x-1); 12 } 13 int sum(int x){ //计算前x项的和 14 int s=0; 15 while(x>0){ 16 s+=bit[x]; 17 x-=lowbit(x); 18 } 19 return s; 20 } 21 //add(),每次添加的范围至少要覆盖全部的范围! 22 void add(int x,int val,int n){ //在x位置上加上val, 更改二叉索引树上的和 ,只能这么添加数 23 while(x<=n){ 24 bit[x]+=val; 25 x+=lowbit(x); 26 } 27 } 28 int main(){ 29 30 int n,k,q; //差分+树状数组 31 while(scanf("%d%d%d",&n,&k,&q)!=EOF){ 32 memset(a,0,sizeof(a)); 33 memset(bit,0,sizeof(bit)); 34 35 int li,ri,maxn=-1; 36 for(int i=1;i<=n;i++){ 37 scanf("%d%d",&li,&ri); 38 a[li]++,a[ri+1]--; 39 maxn=max(maxn,ri); 40 } 41 42 for(int i=1;i<=maxn+1;i++){ 43 a[i]+=a[i-1]; 44 if(a[i]>=k)add(i,1,N-8); 45 } 46 47 while(q--){ 48 scanf("%d%d",&li,&ri); 49 printf("%d\n",sum(ri)-sum(li-1)); 50 } 51 52 } 53 54 return 0; 55 }
你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!