• BZOJ 2298: [HAOI2011]problem a


    2298: [HAOI2011]problem a

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1523  Solved: 756
    [Submit][Status][Discuss]

    Description

    一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)

    Input

    第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi

    Output

    一个整数,表示最少有几个人说谎

    Sample Input

    3

    2 0

    0 2

    2 2



    Sample Output


    1

    HINT


    100%的数据满足: 1≤n≤100000   0≤ai、bi≤n

    题解:

      这个题目还是比较巧妙的。

      首先分析题意,一个人说出的其实是一个区间,表示ai+1~n-bi必须相等,并且其他位置都和这个区间的元素不相等,那么对于两个相交的区间,他们一定有一个是不合法的,对于相等的区间,假如说区间长度为len,那么区间个数超过len的显然超过的部分也是不和法,同理,相互包含的也是不合法的,所以每个区间,我们统计和他相等的区间个数作为权值,这样就转化为选择若干权值不想交的区间使得权值最大化。

      分析到这,就是一个简单dp了,主要还是转化有一定的难度。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #define MAXN 100010
    using namespace std;
    struct node{
        int l,r,maxx;
    }a[MAXN*4];
    struct qvjian{
        int l,r,v;
    }qv[MAXN];
     
    bool cmp(qvjian x,qvjian y){
        if(x.l==y.l) return x.r<y.r;
        else return x.l<y.l;
    }
     
    void pushup(int xv){
        a[xv].maxx=max(a[xv*2].maxx,a[xv*2+1].maxx);
    }
     
    void build(int xv,int l,int r){
        if(l==r){
            a[xv].l=l,a[xv].r=r;
            a[xv].maxx=0;
            return;
        }
        a[xv].l=l,a[xv].r=r;
        int mid=(l+r)/2;
        build(xv*2,l,mid),build(xv*2+1,mid+1,r);
        pushup(xv);
    }
     
    int n,num=0;
     
    int query(int xv,int l,int r){
        int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;
        if(l==L&&r==R){
            return a[xv].maxx;
        }
        if(r<=mid) return query(xv*2,l,r);
        else if(l>mid) return query(xv*2+1,l,r);
        else return max(query(xv*2,l,mid),query(xv*2+1,mid+1,r));
    }
     
    void insert(int xv,int ps,int x){
        int l=a[xv].l,r=a[xv].r,mid=(l+r)/2;
        if(l==r){
            a[xv].maxx=max(a[xv].maxx,x);
            return;
        }
        if(ps<=mid) insert(xv*2,ps,x);
        else insert(xv*2+1,ps,x);
        pushup(xv);
    }
     
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int l,r;scanf("%d%d",&l,&r);
            l=l+1,r=n-r;
            if(l<=r) {qv[++num].l=l;qv[num].r=r,qv[num].v=1;}
        }
        sort(qv+1,qv+num+1,cmp);
        int ps=0;
        for(int i=1;i<=num;i++){
            if(qv[ps].l==qv[i].l&&qv[ps].r==qv[i].r) qv[ps].v++;
            else qv[++ps]=qv[i];
        }
        for(int i=1;i<=ps;i++){
            int len=qv[i].r-qv[i].l+1;
            if(qv[i].v>len) qv[i].v=len;
        }
        build(1,1,n);
        int ans=0;
        for(int i=1;i<=n;i++){
            int now;
            if(qv[i].l-1>0) now=qv[i].v+query(1,1,qv[i].l-1);
            else now=qv[i].v;
            ans=max(ans,now);
            insert(1,qv[i].r,now);
        }
        printf("%d
    ",n-ans);
        return 0;
    }
  • 相关阅读:
    css3 box-shadow
    JS的Document属性和方法
    简单配色方案web
    ps中参考线的使用技巧
    min-width() ie6
    js 模拟右键菜单
    display:table-cell
    js opener 的使用
    js的 new image()
    CSS 中文字体 Unicode 编码方案
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7718786.html
Copyright © 2020-2023  润新知