zoukankan      html  css  js  c++  java
  • Codeforces 567D

    题目链接:https://codeforces.com/problemset/problem/567/D

    题意:

    在一个 $1 imes n$ 的网格上,初始摆放着 $k$ 只船,每只船的长度均为 $a$ 个格子,已知所有船之间均不重叠、不触碰。

    现在Bob每次询问Alice第 $i$ 个格子上是否存在船,Alice每次都会说不存在,求在第几次询问时,可以确定Alice撒谎了。

    题解:

    对于某次询问一个位置 $x$ 是否有船,假设其属于某个最小的区间 $(l,r)$,其中 $l,r$ 分别是曾经询问过的位置。我们用树状数组配合二分 $O(log^2 n)$ 寻找出 $l,r$。

    那么,可以计算出,$(l,r)$ 区间曾经最多能停放多少船只,而现在变成了两个区间 $(l,x)$ 和 $(x,r)$ 后,又能停放多少船只。

    这样一来,最开始我们计算出整个区域 $(0,n+1)$ 最多放多少船只 $cur$,进而对每次计算都能计算出减少了多少船只,即 $cur$ 会减去一个数,直到某一次询问,使得 $cur<k$,即代表Alice撒谎了。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    int n,k,a,m;
    
    struct _BIT
    {
        int N,C[maxn];
        #define lowbit(x) (x&(-x))
        void init(int n) //初始化共有n个点
        {
            N=n;
            for(int i=1;i<=N;i++) C[i]=0;
        }
        void add(int pos,int val) //在pos点加上val
        {
            while(pos<=N)
            {
                C[pos]+=val;
                pos+=lowbit(pos);
            }
        }
        int ask(int pos) //查询1~pos点的和
        {
            int ret=0;
            while(pos>0)
            {
                ret+=C[pos];
                pos-=lowbit(pos);
            }
            return ret;
        }
    }BIT;
    
    int lower(int x)
    {
        int l=1, r=BIT.N;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(BIT.ask(mid)<x) l=mid+1;
            else r=mid;
        }
        return l;
    }
    
    int upper(int x)
    {
        int l=1, r=BIT.N;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(BIT.ask(mid)<=x) l=mid+1;
            else r=mid;
        }
        return l;
    }
    
    int main()
    {
        cin>>n>>k>>a>>m;
    
        BIT.init(n+2);
        BIT.add(1,1), BIT.add(n+2,1);
        int cur=(n+1)/(a+1);
        for(int i=1,x;i<=m;i++)
        {
            scanf("%d",&x), x++;
    
            int tp=BIT.ask(x);
            int l=lower(tp), r=upper(tp);
            int old=(r-l)/(a+1);
            int now=(r-x)/(a+1)+(x-l)/(a+1);
            cur-=old-now;
    
            if(cur<k)
            {
                printf("%d
    ",i);
                return 0;
            }
    
            BIT.add(x,1);
        }
        printf("-1
    ");
    }
  • 相关阅读:
    [USACO11JAN]Roads and Planes G【缩点+Dij+拓补排序】
    Cheatsheet: 2015 05.01 ~ 05.31
    Cheatsheet: 2015 04.01 ~ 04.30
    Cheatsheet: 2015 03.01 ~ 03.31
    Cheatsheet: 2015.02.01 ~ 02.28
    Cheatsheet: 2015 01.01~ 01.31
    Cheatsheet: 2014 12.01 ~ 12.31
    Cheatsheet: 2014 11.01 ~ 11.30
    Cheatsheet: 2014 10.01 ~ 10.30
    Cheatsheet: 2014 09.01 ~ 09.30
  • 原文地址:https://www.cnblogs.com/dilthey/p/10801875.html
Copyright © 2011-2022 走看看