zoukankan      html  css  js  c++  java
  • BZOJ 1594: [Usaco2008 Jan]猜数游戏 线段树 + 思维 + 二分

    Description

    为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力。 游戏开始前,一
    头指定的奶牛会在牛棚后面摆N(1 <= N<= 1,000,000)堆干草,每堆有若干捆,并且没有哪两堆中的草一样多。所
    有草堆排成一条直线,从左到右依次按1..N编号,每堆中草的捆数在1..1,000,000,000之间。 然后,游戏开始。
    另一头参与游戏的奶牛会问那头摆干草的奶牛 Q(1 <= Q <= 25,000)个问题,问题的格式如下: 编号为Ql..Qh(1 
    <= Ql <= Qh <= N)的草堆中,最小的那堆里有多少捆草? 对于每个问题,摆干草的奶牛回答一个数字A,但或许
    是不想让提问的奶牛那么容易地得到答案,又或许是她自己可能记错每堆中干草的捆数,总之,她的回答不保证是
    正确的。 请你帮助提问的奶牛判断一下,摆干草的奶牛的回答是否有自相矛盾之处。

    Input

    * 第1行: 2个用空格隔开的整数:N 和 Q
    * 第2..Q+1行: 每行为3个用空格隔开的整数Ql、Qh、A,描述了一个问题以及它 对应的回答

    Output

    * 第1行: 如果摆干草的奶牛有可能完全正确地回答了这些问题
    (也就是说,能 找到一种使得所有回答都合理的摆放干草的方法),输出0,
    否则输出 1个1..Q中的数,表示这个问题的答案与它之前的那些回答有冲突之处
    注意:如果有冲突出现输出一个数m,使得前M-1个命题不冲突。

     题解: 非常好的一道题.
    考虑什么时候会出现问题(矛盾)
    1.对于同一个数,出现在了两个不相交的区间.
    2.一个区间的最小值已确定,却有一个子区间的最小值小于当前最小值.
    我们先二分一个答案 $mid$ ,把 $1$~$mid$ 的所有操作按照权值从大到小排序.
    每次处理出每一个权值的区间,如果区间有两个或以上,则不合法.
    否则,直接在线段树上查一下该极大区间的区间和.
    如果区间和等于区间长度,说明之前已全部被覆盖掉,这是不合法的.
    否则,直接覆盖当前区间.
    这么迭代下去就行. 

    #include<bits/stdc++.h>
    #define maxn 3000000
    using namespace std;
    void setIO(string s)
    {
        string in=s+".in"; 
        freopen(in.c_str(),"r",stdin); 
    }
    int n,Q;   
    struct OPT
    {
        int l,r,v;    
    }opt[maxn],yy[maxn]; 
    bool cmp(OPT a,OPT b)
    {
        return a.v>b.v; 
    }
    struct Seg
    {
        #define lson (x<<1)
        #define rson ((x<<1)|1)
        int lazy[maxn<<2],sumv[maxn<<2]; 
        void re()
        {
            memset(lazy,0,sizeof(lazy)); 
            memset(sumv,0,sizeof(sumv));    
        }
        void mark(int l,int r,int x)
        {        
            sumv[x]=r-l+1; 
            lazy[x]=1;     
        }
        void pushdown(int l,int r,int x)
        {
            if(lazy[x])
            {
                int mid=(l+r)>>1; 
                if(l<=mid) mark(l,mid,lson); 
                if(r>mid) mark(mid+1,r,rson); 
                lazy[x]=0; 
            }
        }
        void update(int l,int r,int x,int L,int R)
        {
            if(l>=L&&r<=R) 
            {
                mark(l,r,x); 
                return; 
            }
            pushdown(l,r,x); 
            int mid=(l+r)>>1; 
            if(L<=mid) update(l,mid,lson,L,R); 
            if(R>mid) update(mid+1,r,rson,L,R); 
            sumv[x]=sumv[lson]+sumv[rson]; 
        }
        int query(int l,int r,int x,int L,int R)
        {
            if(l>=L&&r<=R) return sumv[x]; 
            pushdown(l,r,x); 
            int mid=(l+r)>>1,tmp=0; 
            if(L<=mid) tmp+=query(l,mid,lson,L,R); 
            if(R>mid)  tmp+=query(mid+1,r,rson,L,R); 
            return tmp;    
        }   
    }tr; 
    bool check(int mid)
    {
        int i,j,k,l1,r1,l2,r2;             
        tr.re(); 
        for(i=1;i<=mid;++i) yy[i]=opt[i]; 
        sort(yy+1,yy+1+mid,cmp); 
        for(i=1;i<=mid;i=j)
        {
            for(j=i;j<=mid&&yy[j].v==yy[i].v;++j); 
            l1=l2=yy[i].l;
            r1=r2=yy[i].r; 
            for(k=i+1;k<j;++k)
            {
                l1=min(l1,yy[k].l); 
                l2=max(l2,yy[k].l); 
                r1=max(r1,yy[k].r); 
                r2=min(r2,yy[k].r); 
            }
            if(l2>r2) return true;     // 无并集
            if(tr.query(1,n,1,l2,r2)==r2-l2+1) return true; 
            tr.update(1,n,1,l1,r1);    
        }
        return false; 
    }
    int main()
    {
        // setIO("input");          
        scanf("%d%d",&n,&Q); 
        for(int i=1;i<=Q;++i)
        {
            scanf("%d%d%d",&opt[i].l,&opt[i].r,&opt[i].v); 
        }    
        int l=1,r=Q,ans=0; 
        while(l<=r)
        {
            int mid=(l+r)>>1; 
            if(check(mid)) 
                r = mid - 1, ans=mid; 
            else 
                l=mid+1; 
        }  
        printf("%d
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    数据库的安装
    数据库大整合
    数据库的设置及其初始密码
    HTML标签
    增加删除的js
    增删改查js
    表单验证码限制条件
    倒序输出插入的数组
    插入数组排序法1
    求下标长度
  • 原文地址:https://www.cnblogs.com/guangheli/p/11040642.html
Copyright © 2011-2022 走看看