• 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中的数,表示这个问题的答案与它之前的那些回答有冲突之处

    Sample Input

    20 4
    1 10 7
    5 19 7
    3 12 8
    11 15 12

    输入说明:

    编号为1..10的草堆中,最小的那堆里有7捆草,编号为5..19的草堆中同样
    如此;编号为3..12的草堆中最小的堆里是8捆草,11..15堆中的最小的堆里是12
    捆。

    Sample Output

    3

    输出说明:

    对于第3个问题“3 12”的回答“8”与前面两个回答冲突。因为每堆中草的
    捆数唯一,从前两个回答中我们能推断出,编号为5..10的干草堆中最小的那堆
    里有7捆干草。很显然,第3个问题的回答与这个推断冲突。

    HINT

    注意:如果有冲突出现输出一个数m,使得前M-1个命题不冲突。

    ————————————————————————————————————

    这道题我们可以二分答案

    然后判断是否有冲突 冲突有两种

    第一种 权值相同的却没有交

    第二种 权值不同 但大的包含小的

    所以我们二分答案的时候 排序之后判断第一种

    第二种涉及到的操作有(线段树)区间覆盖+区间取min 

    我们按权值从大到小操作 区间覆盖取并集 询问取交集

    就可以了 写了蛮久的QAQ

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using std::sort;
    using std::max;
    using std::min;
    const int M=1e5+7,N=3e6+7;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int cnt,n,m,lx[M],rx[M],mn[N],sign[N],ll[M],rr[M];
    struct pos{int l,r,v;}q[M],s[M];
    bool cmp(pos a,pos b){return a.v>b.v;}
    void clear(){
        cnt=1;
        memset(mn,0,sizeof(mn));
        memset(sign,0,sizeof(sign));
    }
    int L,R;
    void up(int x){mn[x]=min(mn[x<<1],mn[x<<1^1]);}
    void down(int x){
        if(!sign[x]) return ;
        int ls=x<<1,rs=x<<1^1;
        sign[x]=0; sign[ls]=sign[rs]=1;
        mn[ls]=mn[rs]=1;
    }
    void modify(int x,int l,int r){
        if(L<=l&&r<=R){
            mn[x]=1; sign[x]=1;
            return ;
        }
        down(x);
        int mid=(l+r)>>1;
        if(L<=mid) modify(x<<1,l,mid);
        if(R>mid) modify(x<<1^1,mid+1,r);
        up(x);
    }
    int push_mn(int x,int l,int r){
        if(L<=l&&r<=R) return mn[x];
        down(x);
        int mid=(l+r)>>1,ans=1;
        if(L<=mid) ans=min(ans,push_mn(x<<1,l,mid));
        if(R>mid) ans=min(ans,push_mn(x<<1^1,mid+1,r));
        return ans;
    }
    bool check(int k){
        if(!k) return 1;
        clear(); 
        for(int i=1;i<=k;i++) s[i]=q[i];
        sort(s+1,s+1+k,cmp);
        int color=s[1].v; 
        lx[1]=s[1].l; rx[1]=s[1].r;
        ll[1]=lx[cnt],rr[1]=rx[cnt];
        for(int i=2;i<=k;i++){
            if(s[i].v!=color){
                cnt++; color=s[i].v;
                lx[cnt]=s[i].l; rx[cnt]=s[i].r;
                ll[cnt]=lx[cnt]; rr[cnt]=rx[cnt];
            }
            else lx[cnt]=min(lx[cnt],s[i].l),rx[cnt]=max(rx[cnt],s[i].r),ll[cnt]=max(ll[cnt],s[i].l),rr[cnt]=min(rr[cnt],s[i].r);
            if(ll[cnt]>rr[cnt]) return 1;
        }
        for(int i=1;i<=cnt;i++){
            L=ll[i]; R=rr[i];
            if(push_mn(1,1,n)!=0) return 1;
            L=lx[i]; R=rx[i];
            modify(1,1,n);
        }
        return 0;
    }
    int main(){
        n=read(); m=read();
        for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].v=read();
        int l=1,r=m+1;
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        if(r>m) printf("0
    ");
        else printf("%d
    ",r);
        return 0;
    }
    View Code
  • 相关阅读:
    持续集成概念
    性能测试,负载测试,压力测试有什么区别
    安全测试
    接口测试及常用接口测试工具
    python-Csv 实战
    Python3 + Appium学习链接
    python-Txt实践
    python-ddt实践
    保险--总结
    selenium与页面的交互
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7612966.html
Copyright © 2020-2023  润新知