码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Round 15

时间:2016-07-31 17:18:36      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

A题 Maximum Increase

大水题。最长连续递增子序列有多长。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int n, a, rec = 0, len = 0, ans = 1;
 7     scanf("%d",&n);
 8     for(int i = 0; i < n; i++)
 9     {
10         scanf("%d", &a);
11         if(a > rec)
12         {
13             rec = a, len++;
14         }
15         else
16             rec = a, len = 1;
17         ans = max(ans, len);
18     }
19     printf("%d\n",ans);
20     return 0;
21 }

 

B题 Powers of Two

这道题有点意思昂,问你有几对,满足巴拉巴拉。

先说一下一开始吧,我的做法是直接暴力两重for循环去做,明显TLE了。一开始没注意n²。

 1 #include <cstdio>
 2 typedef long long LL;
 3 int a[100000+5];
 4 int main()
 5 {
 6     int n;
 7 
 8     scanf("%d", &n);
 9     LL ans = 0;
10     for(int i = 0; i < n; i++)
11     {
12         scanf("%d",a+i);
13     }
14     for(int i = 0; i < n; i++)
15     {
16         for(int j = i+1; j < n; j++)
17         {
18             LL tot = a[i] + a[j];
19             while( (tot & 1) == 0)
20                 tot >>= 1;
21             if(tot == 1)
22                 ans++;
23         }
24     }
25     printf("%lld\n",ans);
26     return 0;
27 }

然后想啊,这TLE咋办,咱剪枝吧。个么,就加了一下这几句话。妄想着能砍掉大部分数据。

bool p1 = a[i] % 2;
bool p2 = a[j] % 2;
if( (p1 && !p2) || (!p1 && p2)) continue;

 

又光荣TLE了。这下给搞急了,还TLE啊。咋办呢,预处理了一个2的幂,然后二分查。

 1 #include <cstdio>
 2 typedef long long LL;
 3 int a[100000+5];
 4 LL J[35];
 5 int main()
 6 {
 7     LL t = 2;
 8     int p = 0;
 9     while(t <= 2000000000 + 5)
10     {
11         J[p++] = t;
12         t <<= 1;
13     }
14 
15     int n;
16 
17     scanf("%d", &n);
18     LL ans = 0;
19     for(int i = 0; i < n; i++)
20     {
21         scanf("%d",a+i);
22     }
23     for(int i = 0; i < n; i++)
24     {
25         for(int j = i+1; j < n; j++)
26         {
27             bool p1 = a[i] % 2;
28             bool p2 = a[j] % 2;
29             if( (p1 && !p2) || (!p1 && p2)) continue;
30             LL tot = a[i] + a[j];
31   
32             int lb = -1, rb = 30;
33             while(rb - lb > 1)
34             {
35                 int mid = (lb + rb) / 2;
36                 if(tot == J[mid])
37                 {ans++;break;}
38                 else if(tot > J[mid])
39                     lb = mid;
40                 else
41                     rb = mid;
42             }
43         }
44     }
45     printf("%lld\n",ans);
46     return 0;
47 }

 

没曾想,又TLE了,orz。。但是!这个预处理,发现一个事,这总共啊,能选的2的幂才30个左右。这就带来了后面的代码的思路。

但这个地方,咱们没认怂,还想。加了个2的幂的位运算的判断方法

bool judge(LL n)
{
    return (n>0) && (!(n&(n-1)));
}

 

人不超时,妄少年啊,你就是死活不肯定动n²的大框架。下面学着点

咋办呢,刚刚不是说了吗这个数据范围,撑死就2的三十次。拿这个做文章。

数据的范围决定了,不能用数组,得用map记录。咋记录啊,ma[x]就代表x出现了几次。咱们就每次输进来个数,然后就检查

我2-x这个数有几个啊,4-x呢,8-x呢,16-x呢,是不是有一个算一个,统统记录到ans里头去啊。最后的统计结果是不是就是答案,又因为你是按输入的时候每输入一个,算一发有几个符合条件的,就间接满足了题目中j>i的要求啊。个么AC了咯。

 1 #include <cstdio>
 2 #include <map>
 3 using namespace std;
 4 typedef long long LL;
 5 map<LL,LL>ma;
 6 int main()
 7 {
 8     int n, x;
 9     LL ans = 0;
10     scanf("%d",&n);
11     for(int i=0;i<n;i++)
12     {
13         scanf("%d",&x);
14         for(int j = 30 ; j >= 0; j--)
15         {
16             LL power = (LL) (1 << j);
17             ans += ma[power - x];
18         }
19         ma[x]++;
20     }
21     printf("%lld",ans);
22     return 0;
23 }

 

然后看到AC后面跟了两个啥数据啊1996 ms 125000 KB,我去这么大啊。那下次不给你三秒的时间,给你1.5秒,你咋办,还能这么做不,明显又被卡成TLE了。咋办,能咋办,再想呗。那这样好不好,框架咱们不动它,还是n*30的复杂度。map咱们也不用了,这次改全部读进来,数组麻溜的存起来。来个排序。干啥呀,干嘛要排序呢。这不从n*30到nlogn了吗。

然后来了,刚刚那个,搜索2的幂-x的方法记得不。这次换个主角,map太贵了。lower_bound和upper_bound。思路不变,实现方法改了而已。跑了一遍样例,发现诶,不对啊,这个错了。

为啥。重复了。重复什么了,他每次会把自己算进去了,这是一方面,还有,它打乱了i和j,还要除以2。

好,这下又AC了,265 ms 200 KB。这就对了嘛看起来舒服多了。

 1 #include <cstdio>
 2 #include <map>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 int a[100000 + 50];
 7 int main()
 8 {
 9     int n;
10     scanf("%d", &n);
11     for(int i = 0; i < n; i++)
12         scanf("%d",a+i);
13     sort(a,a+n);
14     LL ans = 0;
15     for(int i = 0; i < n; i++)
16     {
17         for(int  j = 30; j >= 0; j--)
18         {
19             LL temp = (1 << j) - a[i];
20             int pos1 = lower_bound(a,a+n,temp) - a;
21             int pos2 = upper_bound(a,a+n,temp) - a;
22             ans += pos2 - pos1;
23             if(temp == a[i])
24                 ans--;
25         }
26     }
27     printf("%lld\n", ans/2);
28     return 0;
29 }

 

可是咱还得想啊,要是先想一开始就搞定i和j的先后咋整。

看高亮啊,可以调的参数。

int pos1 = lower_bound(a+i,a+n,temp) - a;
int pos2 = upper_bound(a+i,a+n,temp) - a;

 

 

C题Cellular Network

数据这么大,宝宝很害怕。

典型二分,随便搞。

注意

1 1
-1000000000
1000000000
这组数据把int爆了。。。 所以WA了。所以在longlong边缘的还是上longlong吧。其实是自己分析问题的时候,不够精准。二分的数据范围上判断出了问题。

另外半径是0到2倍的INF。而不是傻兮兮的-INF到INF,也不是0到INF。

 1 #include <cstdio>
 2 const int INF = 1000000000;
 3 const int maxn = 100000 + 50;
 4 typedef long long LL;
 5 int city[maxn], tower[maxn];
 6 int n,m;
 7 bool judge(LL r)
 8 {
 9     int cur = 0;
10     for(int i = 0; i < n; i++)
11     {
12         while(!(city[i] >= (LL) (tower[cur] - r) && city[i] <= (LL) (tower[cur] + r) ) )
13         {
14             cur++;
15             if(cur == m ) return false;
16         }
17     }
18     return true;
19 }
20 int  main()
21 {
22     scanf("%d%d", &n, &m);
23     for(int i = 0; i < n; i++)
24     {
25         scanf("%d", &city[i]);
26     }
27 
28     for(int i = 0; i < m; i++)
29     {
30         scanf("%d", &tower[i]);
31     }
32 
33     LL lb = -1, rb = 2 * INF + 5;
34     while(rb - lb > 1)
35     {
36         LL mid = (lb + rb) / 2;
37         if(judge(mid))
38         {
39             rb = mid;
40         }
41         else
42         {
43             lb = mid;
44         }
45     }
46     printf("%lld\n",rb);
47     return 0;
48 }

 

 

D题Road to Post Office

数学题orz,这个公式很好推。思路也很容易想,直接分三种情况讨论,取最好的情况。

但是!宝宝们,你们有没有想过一件事,怎么取最好情况,有人说,这还不容易的一塌糊涂。。直接min两发不就好了。

你有没有考虑过d<k的时候,第二种情况可能是负数。反正测试数据里面,有两组数据经常会变负数。

d和k的大小关系!!!!!!!!!!!!!!!!!!!!!

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5 LL d,k,a,b,t,ans1,ans2,ans3,ans;
 6 int main()
 7 {
 8     while(cin>>d>>k>>a>>b>>t)
 9     {
10         //一直开车
11         if(d % k == 0)
12             ans1 = t * (d / k - 1) + d * a;
13         else
14             ans1 = t * (d / k ) + d * a;
15         ans = ans1;
16         //只开一次车就步行
17         if(d > k)
18             ans2 = k * a + (d - k) * b, ans = min(ans, ans2);
19 
20         //最后一段路走路
21         if(d > k)
22         {
23             LL d_car = d / k * k;
24             LL d_per = d - d_car;
25             ans3 = d_car * a + d_per * b + t * (d_car / k - 1);
26             ans = min(ans, ans3);
27         }
28         cout<<ans<<endl;
29     }
30     return 0;
31 }

 

Educational Round 15

标签:

原文地址:http://www.cnblogs.com/luosuo10/p/5723145.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!