zoukankan      html  css  js  c++  java
  • P2519 [HAOI2011]problem a(线段树优化dp+思维)

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3
    2 0
    0 2
    2 2
    输出样例#1: 复制
    1

    说明

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




    题目的本质并不难,难点在于对题提转化上:

    比如有一行告诉你,有a个比他大,有b个比他小,那也就是说,前a个比他的并且大小关系不缺定,后b个比他小并且大小关系不确定,他是从a+1到n-y这段区间的数字全相等,这是题目也就转化为了 给你m个区间,每个区间的价值为v,让你选不相交的区间使得得到的价值最大,

    要点:同一个区间可能有多个,使用了map计数。同一个区间的个数不能超过区间的长度。



     1 #include"bits/stdc++.h"
     2 #define lson rt<<1,l,mid
     3 #define rson rt<<1|1,mid+1,r
     4 
     5 using namespace std;
     6 
     7 map<pair<int ,int >,int > mp;
     8 
     9 int tr[4000000];
    10 struct aa
    11 {
    12   int l,r;
    13   bool operator<(const aa b)const
    14   {
    15    return r==b.r?l<b.l:r<b.r;
    16   }
    17 }a[200000]; int tot;
    18 
    19 namespace segtree
    20 {
    21    int que(int rt,int l,int r,int L,int R)
    22    {
    23      if(L>R)return 0;
    24     // cout<<l<<" "<<r<<endl;
    25      if(L<=l&&r<=R)return tr[rt]; int mid=l+r>>1;
    26 int res=-1;     if(L<=mid)res=max(res,que(rt<<1,l,mid,L,R));
    27   if(R>mid)res=max(res,que(rt<<1|1,mid+1,r,L,R));
    28        return res;
    29    }
    30    void upd(int rt,int l,int r,int pos,int v)
    31    {
    32     if(l==r){tr[rt]=max(tr[rt],v);return ;} int mid=l+r>>1;
    33     if(pos<=mid)upd(lson,pos,v);else upd(rson,pos,v);
    34     tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
    35    }
    36 
    37 
    38 }using namespace segtree;
    39 
    40 int dp[200000];
    41 
    42 int main()
    43 {
    44     int n; cin>>n;
    45     for (int i=1;i<=n;i++)
    46     {
    47       int x,y;scanf("%d%d",&y,&x);if(x+y+1>n)continue;
    48        if(!mp[make_pair(x+1,n-y)])
    49        {
    50          a[++tot].l=x+1,a[tot].r=n-y,mp[make_pair(x+1,n-y)]++;
    51        }
    52      else if(mp[make_pair(x+1,n-y)]<n-y-x-1+1)
    53         mp[make_pair(x+1,n-y)]++;
    54 
    55     }
    56     sort(a+1,a+1+tot);
    57 
    58     for (int i=1;i<=tot;i++)
    59     {
    60      dp[a[i].r]=max(dp[a[i].r],que(1,0,n,0,a[i].l-1)+mp[make_pair(a[i].l,a[i].r)]);//cout<<i<<endl;
    61      upd(1,0,n,a[i].r,dp[a[i].r]);
    62     }
    63     int ans=0;
    64     for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
    65     cout<<n-ans;
    66 
    67 
    68 
    69 
    70 
    71 }
  • 相关阅读:
    委托
    队列和栈、泛型
    Java去除字符串中 除数字和逗号以外的符号
    SQL查询重复记录
    使用EasyExcel导出图片及异常处理
    Nacos开机自启
    Redis开机自启
    Nginx开机自启
    Java 向数组中添加元素
    Java:如何打印整个字符串数组?
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10498142.html
Copyright © 2011-2022 走看看