UVA 12663(线段树+二分)

UVA 12663(线段树+二分)_第1张图片

UVA 12663(线段树+二分)_第2张图片




题意:现在有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;
}


你可能感兴趣的:(-----数据结构-----,线段树,二分,-----基础算法-----)