题目大意:给n个桥,m次潮涨落,给定潮涨落的高度,问被淹没次数大于等于k的桥的个数,对于一直被淹没的,只记录一次。
把不同高度的桥看做坐标不同的点,然后潮涨落就相当于一次区间修改 修改的是上次潮落位置+1的桥到本次潮涨的位置,输出答案时需要访问到每个叶子结点。
AC代码
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define ls k<<1
#define rs k<<1|1
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define mid ((l+r)>>1)
#define laz(rt) tr[rt].laz
#define sum(rt) tr[rt].sum
const int maxn=100101;
int a[maxn];
int ki,cnt,n,m;
struct node{
int sum,laz;
}tr[maxn<<2];
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
inline void down(int k){
sum(ls)+=laz(k);sum(rs)+=laz(k);
laz(ls)+=laz(k);laz(rs)+=laz(k);
laz(k)=0;
}
void build(int k,int l,int r){
laz(k)=sum(k)=0;
if(l==r)return ;
build(lson);build(rson);
}
void change(int k,int l,int r,int x,int y,int v){
if(x<=l&&y>=r){
laz(k)+=v;sum(k)+=v;
return ;
}
if(laz(k))down(k);
if(x<=mid)change(lson,x,y,v);
if(y>mid)change(rson,x,y,v);
}
int ask(int k,int l,int r){
if(l==r)
return sum(k)>=ki;
if(laz(k))down(k);
return ask(lson)+ask(rson);
}
int c[maxn],d[maxn],x,y;
int main(){
while(scanf("%d%d%d",&n,&m,&ki)!=EOF){
for(int i=1;i<=n;i++)
a[i]=read();
sort(a+1,a+n+1);
build(1,1,n);
d[0]=0;
for(int i=1;i<=m;i++){
c[i]=read();d[i]=read();
x=lower_bound(a+1,a+n+1,d[i-1]+1)-a;
y=upper_bound(a+1,a+n+1,c[i])-a;
if(a[y]>c[i])y--;
change(1,1,n,x,y,1);
}
printf("Case %d: %d\n",++cnt,ask(1,1,n));
}
return 0;
}