题意:现在有N座桥,给出每个桥的高度,现在会发M次的洪水,每次洪水会涨至A高度,然后退回B的高度,问有多少桥至少被淹没了K次。
题解:
先吐槽一下:唉,人太蠢怎么办?连二分都没有想到,其实这一题的key就是想到二分,想到二分去解决,那么这一题就是模板题了。吐槽完毕
很明显直接模拟会超时。
考虑使用二分,查找高度在B[I-1],到A[I]高度的桥,即在大小在[A[I],B[I-1]]这个区间算一次淹没,然后就是这个区间每个桥淹次数+1次,直接使用线段树区间更新,复杂度M*logN
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define N 100005
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
int arr1[N];
struct point
{
int lc,rc;
int add;
int sum;
}tree[N<<2];
int num=0;
void pushdown(int rt,int leg)
{
if(tree[rt].add)
{
tree[rt<<1].sum+=tree[rt].add*(leg-(leg>>1));
tree[rt<<1|1].sum+=tree[rt].add*((leg>>1));
tree[rt<<1].add+=tree[rt].add;
tree[rt<<1|1].add+=tree[rt].add;
tree[rt].add=0;
}
}
void build(int L,int R,int rt)
{
tree[rt].lc=L;
tree[rt].rc=R;
tree[rt].add=0; tree[rt].sum=0;
if(L==R)
{
return;
}
int mid=(L+R)>>1;
build(L,mid,rt<<1);
build(mid+1,R,rt<<1|1);
}
void update(int L,int R,int c,int rt)
{
if(tree[rt].lc==L&&tree[rt].rc==R)
{
tree[rt].sum+=c*(R-L+1);
tree[rt].add+=c;
return;
}
pushdown(rt,tree[rt].rc-tree[rt].lc+1);
int mid=(tree[rt].rc+tree[rt].lc)>>1;
if(R<=mid)update(L,R,c,rt<<1);
else if(L>mid)update(L,R,c,rt<<1|1);
else{
update(L,mid,c,rt<<1);
update(mid+1,R,c,rt<<1|1);
}
}
void query(int L,int R,int rt)
{
if(L==tree[rt].lc&&tree[rt].rc==R)
{
num+=tree[rt].sum;
return ;
}
pushdown(rt,tree[rt].rc-tree[rt].lc+1);
int mid=(tree[rt].lc+tree[rt].rc)>>1;
if(R<=mid)
{
query(L,R,rt<<1);
}
else if(L>mid)
query(L,R,rt<<1|1);
else
{
query(L,mid,rt<<1);
query(mid+1,R,rt<<1|1);
}
}
int main()
{
#ifdef CDZSC
freopen("i.txt","r",stdin);
#endif
int k,n,m,a,b,cas=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
build(1,n,1);
int high=1;
for(int i=1;i<=n;i++)
{
scanf("%d",&arr1[i]);
}
sort(arr1+1,arr1+n+1);
while(m--)
{
scanf("%d%d",&a,&b);
int idx1=lower_bound(arr1+1,arr1+1+n,high)-arr1;
int idx2=lower_bound(arr1+1,arr1+1+n,a)-arr1;
if(idx2>n)idx2=n;
while(arr1[idx1]<=high)idx1++;
while(a=k)ans++;
}
printf("Case %d: %d\n",++cas,ans);
}
return 0;
}