• hdu4614 二分法+段树



    意甲冠军:给你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.
    ");
                    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
    ",star-1,end-1);
                        update(1,n,star,end,1,-1);
                    }
                }
                else
                {
                    printf("%d
    ",b-a+1-find(1,n,a+1,b+1,1));
                    update(1,n,a+1,b+1,1,1);
                }
                
            }
            printf("
    ");    
        }
        return 0;    
    }
    

  • 相关阅读:
    POJ2524+并查集
    POJ3697+BFS+hash存边
    POJ1151+线段树+扫描线
    POJ2528+线段树
    ubuntu 和 win7 远程登陆 + vnc登陆
    POJ3690+位运算
    POJ3283+字典树
    POJ3282+模拟
    POJ2349+prim
    2016.6.13
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4595119.html
Copyright © 2020-2023  润新知