1003 真实的谎言

1003 真实的谎言

这是一个非常有趣的题目,题目描述很简练,但却卡住了很多人。其实,这个题并不难,也没有什么需要注意的地方,只要有了思路,基本就正确了。但是,切忌一一枚举,这样的结果只有一个——TLE。不过只要有了枚举这个想法,在适当思考,加以优化,基本就能AC了。首先,我们来说下暴力枚举的思路:定义一个结构体保存输入,输入完成后,执行

 
  
bool flag = 0 ;
for ( int i = n - 1 ;i >= 0 ;i -- )
{
int ans = 0 ;
for ( int j = 0 ;j < n;j ++ )
if (a[j].min <= i && a[j].max >= i) count ++ ;
if (count == i) {flag = 1 ;cout << i << endl; break ;}
}
if (flag == 0 ) cout << " -1 " << endl;

当然,这样做的效率是很低的,是会TLE的,但是在这却能让我们从中得到启示:外层循环:我们假设有 i 个人说真话,我们就需要利用内层循环遍历数组,检查是否是有 i 个人说真话,如果 i 在区间内,就计数加1,这样,通过n次遍历,我们就可以找出包含了 i 的区间个数,如果包含 i 的区间个数等于 i ,那么就有 i 个人说了真话。又我们是 i :  n-1一>0 ,所以一旦成立,那么就是我们的最优解,如果所有均不成立,那么flag=0,输出-1。既然如此,我们完全可以在输入过程中完成遍历处理:设一个数组count[100001],在输入过程中加以处理,

 
  
int count[ 100001 ] = { 0 },a,b;
for ( int i = 0 ;i < n;i ++ )
{ cin
>> a >> b;
for ( int j = a;j <= b;j ++ )
count[j]
+= 1 ;
}

这个过程中,我们统计了包含 i 的区间个数 count[i],最后我们只需要从大到小同上检索一遍,就能得到正确解了

下面是我的AC代码,大家可以参考一下,但不要直接拷贝提交,也不要太过依赖于它!

ContractedBlock.gif ExpandedBlockStart.gif View Code
 
   
1 #include < iostream >
2 #include < cstdio >
3   using namespace std;
4   int main()
5 { int T,n;
6 cin >> T;
7 while (T -- )
8 { bool flag = 0 ;
9 int a[ 100001 ] = { 0 },b,c,m,i,j,k;
10 cin >> n;m = n;
11 for (i = 0 ;i < n;i ++ )
12 { scanf( " %d %d " , & b, & c);
13 for (j = b;j <= c && j <= n;j ++ ) a[j] += 1 ;
14 }
15 for (i = n;i > 0 ;i -- )
16 if (a[i] == i) {flag = 1 ,cout << i << endl; break ;}
17 if (flag == 0 ) cout << " -1 " << endl;
18 }
19 }
20

转载于:https://www.cnblogs.com/gcb-1991/archive/2011/04/16/2018472.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值