Hdu 4614 线段树


这题很精巧,可以转化成如下五个操作
1.放花:置0
2.清理:置1
3.清理的输出:查找1的个数
4.放花的输出:
      1)查找0的个数
  2)查找第k个0所在位置


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define N 50005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define initial 0,n-1,1
#define pb push_back
#define mp make_pair
using namespace std;
int n,m;

struct segtree{
    int  a0[N<<2],a1[N<<2],lazy[N<<2];
    void up(int rt)
        {
            a0[rt]=a0[rt<<1]+a0[rt<<1|1];
            a1[rt]=a1[rt<<1]+a1[rt<<1|1];
        }
    void build(int l,int r,int rt)
        {   lazy[rt]=0;
            if (l==r) {     a1[rt]=0;
                            a0[rt]=1;
                            return;
                      }

            int mid=(l+r)>>1;
            build(lson);
            build(rson);
            up(rt);
        }

    void fun(int rt,int op,int m)
        {   if (op==1)
                 {      a0[rt]=m; a1[rt]=0; }
            if (op==2)
                 {      a0[rt]=0; a1[rt]=m; }

            lazy[rt]=op;
        }
    void down(int rt,int m)
        {
            if (lazy[rt])
                {   fun(rt<<1,lazy[rt],m-(m>>1));
                    fun(rt<<1|1,lazy[rt],m>>1);
                    lazy[rt]=0;
                }
        }
    void update(int L,int R,int op,int l,int r,int rt)
        {   if (L<=l&&r<=R)
                {   fun(rt,op,r-l+1);
                    return;
                }
            down(rt,r-l+1);
            int mid=(l+r)>>1;
            if (L<=mid) update(L,R,op,lson);
            if (mid<R)  update(L,R,op,rson);
            up(rt);
        }
    int find(int c,int l,int r,int rt)
        {   if (l==r) return l;
            down(rt,r-l+1);
            int mid=(l+r)>>1;
            int re;
            if (a0[rt<<1]>=c) re=find(c,lson);else re=find(c-a0[rt<<1],rson);
            up(rt);
            return re;

        }
       int query(int L,int R,int op,int l,int r,int rt)
        {   if (L<=l&&r<=R) {
                                 if (op==0)return a0[rt];
                                 if (op==1)return a1[rt];
                            }
            down(rt,r-l+1);
            int mid=(l+r)>>1;
            int re=0;
            if (L<=mid) re+=query(L,R,op,lson);
            if (mid<R)  re+=query(L,R,op,rson);
            up(rt);
            return re;
        }
}st;


void doit()
{   char ss[12];
    int x,y,z;
    scanf("%d%d",&n,&m);
    st.build(initial);
    while (m--)
        {   scanf("%d%d%d",&x,&y,&z);
            if (x==1)
                {

                    int tmp,left,ans1,ans2;
                    if (y!=0) tmp=st.query(0,y-1,0,initial);else tmp=0;
                    left=st.query(y,n-1,0,initial);
                    if (left==0)  {printf("Can not put any one.\n"); continue;}
                    ans1=st.find(tmp+1,initial);
                    ans2=st.find(tmp+min(left,z),initial);
                    printf("%d %d\n",ans1,ans2);
                    st.update(ans1,ans2,2,initial);

                }
             if (x==2)
                {   printf("%d\n",st.query(y,z,1,initial));
                    st.update(y,z,1,initial);
                }
        }

}

int main()
{   int cas;
    scanf("%d",&cas);
    while (cas--) {doit();printf("\n");}
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值