记录一个菜逼的成长。。
题目大意:
n区间,q次查询区间
每次查询有多少个点是在n个区间里出现了k次的
一开始看到这题想的就是线段树。
后来看到题解和别人的代码,发现,原来还有这种操作?
n个区间的处理
给你区间
[l,r]
c[l]++,c[r+1]–;
这样能保证前缀和就是这个点的出现次数
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
int c[maxn],sum[maxn];
int main()
{
int n,k,q;
while(~scanf("%d%d%d",&n,&k,&q)){
for( int i = 1; i <= n; i++ ){
int a,b;
scanf("%d%d",&a,&b);
c[a]++,c[b+1]--;
}
for( int i = 1; i <= 200000; i++ ){
c[i] += c[i-1];
sum[i] += sum[i-1];
if(c[i] >= k)sum[i] += 1;
}
while(q--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",sum[r] - sum[l-1]);
}
}
return 0;
}
线段树版本
#include <bits/stdc++.h>
using namespace std;
#define lson t<<1,l,mid
#define rson t<<1|1,mid+1,r
#define seglen(t) (T[t].r-T[t].l+1)
const int maxn = 200000 + 10;
struct Node{
int l,r,sum,lazy;
}T[maxn<<2];
int n,k,q;
int a[maxn];
void pushup(int t)
{
T[t].sum = T[t<<1].sum + T[t<<1|1].sum;
}
void pushdown(int t)
{
if(T[t].lazy){
T[t<<1].lazy += T[t].lazy;
T[t<<1|1].lazy += T[t].lazy;
T[t<<1].sum += T[t].lazy * seglen(t<<1);
T[t<<1|1].sum += T[t].lazy * seglen(t<<1|1);
T[t].lazy = 0;
}
}
void build(int t,int l,int r)
{
T[t].l = l;
T[t].r = r;
T[t].lazy = 0;
if(l == r){
T[t].sum = 0;
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(t);
}
void update(int t,int l,int r)
{
if(l <= T[t].l && T[t].r <= r){
T[t].lazy += 1;
T[t].sum += seglen(t);
return ;
}
pushdown(t);
int mid = (T[t].l + T[t].r) >> 1;
if(l <= mid)update(t<<1,l,r);
if(r > mid)update(t<<1|1,l,r);
pushup(t);
}
int query(int t,int l,int r)
{
if(l <= T[t].l && T[t].r <= r){
return T[t].sum;
}
pushdown(t);
int ret = 0;
int mid = (T[t].l + T[t].r) >> 1;
if(l <= mid)ret += query(t<<1,l,r);
if(r > mid)ret += query(t<<1|1,l,r);
pushup(t);
return ret;
}
int main()
{
while(~scanf("%d%d%d",&n,&k,&q)){
build(1,1,200000);
for( int i = 1; i <= n; i++ ){
int a,b;
scanf("%d%d",&a,&b);
update(1,a,b);
}
for( int i = 1; i <= 200000; i++ ){
a[i] += a[i-1];
if(query(1,i,i) >= k)a[i] += 1;
}
while(q--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",a[r] - a[l-1]);
}
}
return 0;
}