hdu 4614 线段树+二分

这题感觉有点坑,数组越界了,看来以后数组要尽可能的开大一些了。
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 60005
struct ee
{
int l,r,flag,length;
}tree[maxn*4];
int n,m;

void build(int a,int l,int r)
{
    tree[a].l=l;
    tree[a].r=r;
    tree[a].flag=-1;
    tree[a].length=0;
    if(l==r)
        return;
    int mid=(l+r)/2;
    build(a*2,l,mid);
    build(a*2+1,mid+1,r);
}

void pushup(int a)
{
    tree[a].length=tree[a*2].length+tree[a*2+1].length;
}

void pushdown(int a,int flag)
{
    tree[a*2].flag=flag;
    tree[a*2].length=flag*(tree[a*2].r+1-tree[a*2].l);
    tree[a*2+1].flag=flag;
    tree[a*2+1].length=flag*(tree[a*2+1].r+1-tree[a*2+1].l);
}

int query(int a,int l,int r)
{
    int ans=0;
    if(tree[a].flag!=-1)
    {
        pushdown(a,tree[a].flag);
        tree[a].length=(tree[a].r-tree[a].l+1)*tree[a].flag;
        tree[a].flag=-1;
    }
    if(l<=tree[a].l&&tree[a].r<=r)
        return tree[a].length;
    int mid=(tree[a].r+tree[a].l)/2;
    if(l<=mid)
        ans+=query(a*2,l,r);
    if(mid+1<=r)
        ans+=query(a*2+1,l,r);
    return ans;
}

int find(int a,int num)                         //这点以后要注意了,根据空位来查找,因为树节点间接记录了空位长度的信息,如果根据点或者直接用query来查找的话,时间复杂度多了lg(n),关键是不好找具体结尾的位置
{
    int ans;
    if(tree[a].flag!=-1)
    {
        tree[a].length=tree[a].flag*(tree[a].r+1-tree[a].l);
        pushdown(a,tree[a].flag);
        tree[a].flag=-1;
    }
    if(tree[a].r==tree[a].l)
        return tree[a].r;
    if(tree[a*2].r+1-tree[a*2].l-tree[a*2].length<num)
    {
        ans=find(a*2+1,num-(tree[a*2].r+1-tree[a*2].l-tree[a*2].length));
    }
    else
        ans=find(a*2,num);
    return ans;
}

void change(int a,int l,int r,int flag)
{
    if(l<=tree[a].l&&tree[a].r<=r)
    {
        tree[a].flag=flag;
        tree[a].length=flag*(tree[a].r+1-tree[a].l);
        return;
    }
    if(tree[a].flag!=-1)
    {
        tree[a].length=tree[a].flag*(tree[a].r+1-tree[a].l);
        pushdown(a,tree[a].flag);
        tree[a].flag=-1;
    }
    int mid=(tree[a].r+tree[a].l)/2;
    if(l<=mid)
        change(a*2,l,r,flag);
    if(mid<r)
        change(a*2+1,l,r,flag);
    pushup(a);
}

int main()
{
    int T;
    //freopen("d:\\in.txt","r",stdin);
    scanf("%d",&T);
    while(T)
    {
    scanf("%d%d",&n,&m);
    int i;
    build(1,0,n-1);
      for(i=1;i<=m;i++)
      {
        int k;
        scanf("%d",&k);
        if(k==1)
        {
           int a,b,cnt;
           scanf("%d%d",&a,&b);
           cnt=n-a-query(1,a,n-1);
           if(cnt==0)
            printf("Can not put any one.\n");
           else
           {
             int sta,end,s,e;
             if(a!=0)
                sta=a-query(1,0,a-1)+1;
             else
                sta=1;
             s=find(1,sta);
             if(cnt<b)
             {
                 end=sta+cnt-1;
                 e=find(1,end);
             }
             else
             {
                end=sta+b-1;
                e=find(1,end);
             }
             change(1,s,e,1);
             printf("%d %d\n",s,e);
           }
        }
        else
        {
           int a,b;
           scanf("%d%d",&a,&b);
           int tt=b-a+1-query(1,a,b);
           change(1,a,b,0);
           tt=b-a+1-query(1,a,b)-tt;
           printf("%d\n",tt);
        }
      }
     printf("\n");
     T--;
    }
    return 0;
}


你可能感兴趣的:(hdu 4614 线段树+二分)