hdu4614 二分+线段树

来源:互联网 发布:算法问题实战策略好吗 编辑:程序博客网 时间:2024/05/14 10:55


题意:给你1-n的花瓶   ,刚开始全是空的,现在有两种操作,

1:从花瓶a开始插入b朵花          如果不能插进去  输出字符串  否则输出最多插入的起点和终点;

2:把a-b的花瓶清空   输出处理花的个数;

结构体数组num【i】表示节点i空瓶的数目

线段树   开始deal函数对整个树初始化,update()更新函数 find()查询区间有多少个空瓶;     对于操作1    关键点是找到起点和终点   这里用二分  在【a,n】进行二分,

先二分起点       注意左右区间的变换(wa了好多次==)   然后在起点和n之间二分终点   最后更新  输出     对于操作2     直接查询即可;


#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define LL(x) (x<<1)#define RR(x) ((x<<1)|1)struct node{    int cont;}num[50000*4];int deal(int L,int R,int point){    num[point].cont=R-L+1;    if(L==R) return 0;    int mid=(L+R)/2;    deal(L,mid,LL(point));    deal(mid+1,R,RR(point));    return 0;    }int update(int L,int R,int left,int right,int point,int k){    if(L==left&&R==right)    {        if(k==1) num[point].cont=R-L+1;        else num[point].cont=0;        return 0;    }    int mid=(L+R)/2;    if(num[point].cont==R-L+1)    {        num[LL(point)].cont=mid-L+1;        num[RR(point)].cont=R-mid;    }    if(num[point].cont==0)    {        num[LL(point)].cont=0;        num[RR(point)].cont=0;    }    if(right<=mid)    {        update(L,mid,left,right,LL(point),k);    }    else if(left>mid)    {        update(mid+1,R,left,right,RR(point),k);    }    else    {        update(L,mid,left,mid,LL(point),k);        update(mid+1,R,mid+1,right,RR(point),k);    }    num[point].cont=num[LL(point)].cont+num[RR(point)].cont;    return 0;}int find(int L,int R,int left,int right,int point){    if(L==left&&R==right)    return num[point].cont;    int sum=0;    int mid=(L+R)/2;    if(num[point].cont==R-L+1) return right-left+1;    if(num[point].cont==0) return 0;    if(right<=mid) sum+=find(L,mid,left,right,LL(point));    else if(left>mid) sum+=find(mid+1,R,left,right,RR(point));    else    {        sum+=find(L,mid,left,mid,LL(point));        sum+=find(mid+1,R,mid+1,right,RR(point));    }    return sum;}int main(){    int n,m,k,i,j,T,a,b;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        deal(1,n,1);        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&k,&a,&b);            if(k==1)            {                a+=1;                int cont=find(1,n,a,n,1);                if(cont==0) printf("Can not put any one.\n");                else                {                    int left,right,mid;                    int star,end;                    left=a;                    right=n;                    while(left<=right)                    {                        mid=(left+right)/2;                        if(find(1,n,left,mid,1)>0)                        {                            right=mid-1;                            star=mid;                        }                        else left=mid+1;                                             }                    if(cont<=b)                    {                        left=a;                        right=n;                        while(left<=right)                        {                            mid=(left+right)/2;                            if(find(1,n,mid,right,1)>0)                            {                                left=mid+1;                                end=mid;                            }                            else right=mid-1;                                }                        //end=right;                    }                        else                    {                        left=a;                        right=n;                        while(left<=right)                        {                            mid=(left+right)/2;                            if(find(1,n,star,mid,1)>=b)                            {                                right=mid-1;                                end=mid;                            }                            else left=mid+1;                        }                        //end=left;                    }                    printf("%d %d\n",star-1,end-1);                    update(1,n,star,end,1,-1);                }            }            else            {                printf("%d\n",b-a+1-find(1,n,a+1,b+1,1));                update(1,n,a+1,b+1,1,1);            }                    }        printf("\n");        }    return 0;    }

0 0
原创粉丝点击