题目链接:http://acm.hi-54.com/problem.php?pid=2098
2098 : Drink coffee
时间限制:1 Sec 内存限制:256 MiB
提交:32
答案正确:9
题目描述
为了在上课时保持清醒,凯伦需要一些咖啡。咖啡爱好者凯伦想知道最佳的温度来冲煮完美的咖啡。因此,她花了一些时间阅读几本食谱,其中包括广受好评的“咖啡的艺术”。
她知道有n个食谱,其中第i个食谱建议应当在li和ri度之间冲煮以达到最佳的味道。凯伦认为如果至少k个食谱推荐某个温度,那么那个温度是可以接受的。
凯伦的性格比较多变,因此她会问q个问题,对于每一个问题,她会给出一个温度区间[a,b],你要告诉她有多少可接受的整数温度在这个范围内。
输入
第一行输入包含三个整数,n,k(1≤k≤n≤200000)和q(1≤q≤200000),如题中所描述。
接下来n行描述每一个食谱,具体来说,其中的第i行包含两个整数li和ri(1≤li≤ri≤200000),描述第i个食谱建议咖啡在li和ri度之间进行冲煮(包括端值)。
接下来q行为q个询问。这些行中的每一行都包含a和b,(1≤a≤b≤200000),表示她想知道a和b度之间的可接受的整数温度的数量,包括a和b。
输出
对于每个询问,输出一个答案。
样例输入
复制
3 2 4 91 94 92 97 97 99 92 94 93 97 95 96 90 100
样例输出
复制
3 3 0 4
题意就是先给几个区间,每次都对区间中所有元素累加一次,
最后询问Q次,问在某个区间内次数大于k这样的数字有几个。
就是个裸的树状数组啊,可是以前刷树状数组的时候没写过区间更新区间查询的题,太久没写树状数组,突然手生,比赛时候没写出来。
然后这道题,用到了差分的思想,每次对区间开始和结束进行差分标记(等等,好像写过类似的,想起来了当时写HDU1556
还写了这个博客)no wonder感觉在哪见过类似思想。
赛后补了下区间修改,看了这个博客:https://blog.csdn.net/noiau/article/details/76531671
我应该会了,吧?
哦,对了本题AC代码:
#include<cstdio> #include<iostream> #include <cstring> #include <algorithm> #include <queue> #include<cmath> #define ll long long using namespace std; const int maxn=2e5+10; int Tree[maxn],n,ans[maxn],sum[maxn]; inline int lowbit(int x) { return (x&-x); } void add(int x,int val) { for(int i=x;i<maxn;i+=lowbit(i)) Tree[i]+=val; } int get(int x,int y) { int sum1=0,sum2=0; for(int i=x;i>0;i-=lowbit(i)) sum1+=Tree[i]; for(int i=y;i>0;i-=lowbit(i)) sum2+=Tree[i]; return sum2-sum1; } int main() { int n,k,q,x,y; while(~scanf("%d%d%d",&n,&k,&q)) { memset(Tree,0,sizeof(Tree)); memset(ans,0,sizeof(ans)); memset(sum,0,sizeof(sum)); for(int i=0;i<n;i++) { scanf("%d%d",&x,&y); ans[x]++; ans[y+1]--; } for(int i=1;i<=maxn;i++) { sum[i]=sum[i-1]+ans[i]; if(sum[i]>=k) add(i,1); } for(int i=1;i<=q;i++) { scanf("%d%d",&x,&y); printf("%d ",get(x-1,y)); } } return 0; }