zoukankan      html  css  js  c++  java
  • BZOJ2298 [HAOI2011]problem a 【dp】

    题目

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

    输入格式

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

    输出格式

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

    输入样例

    3

    2 0

    0 2

    2 2

    输出样例

    1

    提示

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

    题解

    一个人的话意思就是自己的分数排名在区间([a_i + 1,n - b_i])之间,且这个区间内的分数都相等
    那么我们现在有(n)个这样的区间
    先去掉那些(l > r)的区间
    由于相等的区间具有相同的真假性,我们可以合并
    相交的区间不能共存,问题就转化为了选若干个带权区间不相交的最大值

    (r)排序,设(f[i])为第(i)个区间为止的最大答案
    我们只需找到最大的(j<i)使得(r_j <l_i),那么

    [f[i] = max(f[i - 1],f[j] + v_i) ]

    可以二分查找

    (n - f[m])就是答案

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 100005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    struct inter{
    	int l,r,v;
    }e[maxn];
    inline bool operator <(const inter& a,const inter& b){
    	return a.l == b.l ? a.r < b.r : a.l < b.l;
    }
    inline bool cmp(const inter& a,const inter& b){
    	return a.r == b.r ? a.l < b.l : a.r < b.r;
    }
    int n,tot,f[maxn];
    int find(int l,int r,int x){
    	int mid;
    	while (l < r){
    		mid = l + r + 1 >> 1;
    		if (e[mid].r < x) l = mid;
    		else r = mid - 1;
    	}
    	return l;
    }
    int main(){
    	int tn;
    	tn = n = read();
    	REP(i,n){
    		e[i].l = read() + 1;
    		e[i].r = n - read();
    		e[i].v = 1;
    	}
    	tot = 0;
    	for (int i = 1; i <= n; i++)
    		if (e[i].l <= e[i].r) e[++tot] = e[i];
    	n = tot;
    	sort(e + 1,e + 1 + n);
    	tot = 1;
    	for (int i = 2; i <= n; i++)
    		if (e[i].l == e[tot].l && e[i].r == e[tot].r)
    			e[tot].v++;
    		else e[++tot] = e[i];
    	REP(i,tot) e[i].v = min(e[i].v,e[i].r - e[i].l + 1);
    	sort(e + 1,e + 1 + tot,cmp);
    	f[1] = e[1].v;
    	for (int i = 2; i <= tot; i++){
    		int pre = find(0,i - 1,e[i].l);
    		f[i] = max(f[i - 1],f[pre] + e[i].v);
    	}
    	printf("%d
    ",tn - f[tot]);
    	return 0;
    }
    
    
  • 相关阅读:
    编写Excel文件的Golang库
    Go多组Raft库
    Go GraphQL初学者教程
    简洁架构的思想,基于go实现
    gometalinter代码质量检查分析工具(golang)
    用go实现一个redis-cli
    Sublime text —— 自定义主题Soda
    Sublime text —— 自定义Color theme
    Sublime Text增加Build system类型,打造一个全能IDE
    一个简单的增强型PHP curl函数
  • 原文地址:https://www.cnblogs.com/Mychael/p/8882068.html
Copyright © 2011-2022 走看看