Codeforces 990E Post Lamps 【暴力】【贪心】

虽然只是10^6的数据量,但用cin会tle。一直知道cin常数大,但没想到会是10^3这个级别,而且比scanf慢5倍左右。

我们枚举每个power的lamp,然后对每个power用平均logn的代价去求它的cost,最后取最小值

对于每个power,我们从左往右地去照亮整个区间,首先0点要插一个路灯,下一个路灯理想上想插在0+power的位置(这样区间不被重复照亮),但实际上power位置上的路灯可能被blocked了,所以我们想在power位置之前的离power最近的一个位置安装路灯。如果发现最近的那个位置离power的位置大于power了,那power位置永远不会被照亮,返回-1

这样贪心实际上每次算cost的代价是 n/power,为什么平均意义下是logn的呢。

因为整体下来是n/1+n/2+n/3+n/4+...+n/k,可见k越大整体复杂度越高,我们考虑其上限及k=n的情况,得到n(1+1/2+1/3+1/4+...+1/n),而1+1/2+1/3+1/4+1/5+...+1/n这个数列求和是logn级别的因为可以把1/3+1/4看成1/2,1/5+1/6+1/7+1/8看成1/2,接下来的每8项,16项都是1/2。然后把n看成2^k的话也可以把n看成2^0+2^1+2^2+...+2^k-1,其中每一份都对数列的和贡献出1/2,所以这个数列求和是1/2*logn左右,及logn级别的。

 1 #include<iostream>
 2 using namespace std;
 3
 4 int n,m,k;//长度为n,m个
 5 int cost[1000005],blocked[1000005],last_unblocked[1000005];
 6 long long ans;
 7 int main()
 8 {
 9     cin>>n>>m>>k;
10     for(int i=1;i<=m;i++){
11         int x; scanf("%d",&x);
12         blocked[x]=1;
13     }
14     for(int i=1;i<=k;i++) scanf("%d",&cost[i]); //power为i的lamp花费cost[i]
15     if(blocked[0]) { cout<<-1; return 0; }
16
17     int last=0;
18     for(int i=1;i<=n;i++){
19         if(!blocked[i]) last=i;
20         last_unblocked[i]=last;
21     }
22     for(int i=1;i<=k;i++){//模拟用每个power的路灯
23         long long c=0;
24         for(int index=0;index<n; ){//index是每一个要插路灯的位置
25             c+=cost[i];
26             if(index+i>=n) index=n;
27             else{
28                 int loc=last_unblocked[index+i];//下一个路灯想插在index+i,但这里可能被blocked了,那想照亮这个地方就找这个位置前面最近能放路灯的位置
29                 if(loc<=index) { c=-1; break; }
30                 index=loc;
31             }
32         }
33         if(c==-1) continue;
34         else{
35             if(ans==0) ans=c;
36             else ans=min(c,ans);
37         }
38     }
39
40     if(ans==0) cout<<-1;
41     else  cout<<ans;
42     return 0;
43 }

原文地址:https://www.cnblogs.com/ZhenghangHu/p/9191168.html

时间: 2024-10-10 21:05:11

Codeforces 990E Post Lamps 【暴力】【贪心】的相关文章

Codeforces 442B Andrey and Problem(贪心)

题目链接:Codeforces 442B Andrey and Problem 题目大意:Andrey有一个问题,想要朋友们为自己出一道题,现在他有n个朋友,每个朋友想出题目的概率为pi,但是他可以同时向多个人寻求帮助,不过他只能要一道题,也就是如果他向两个人寻求帮助,如果两个人都成功出题,也是不可以的. 解题思路:贪心,从概率最大的人开始考虑,如果询问他使得概率变大,则要询问. #include <cstdio> #include <cstring> #include <a

Codeforces Round #300-Tourist&#39;s Notes(贪心)

Tourist's Notes Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Description A tourist hiked along the mountain range. The hike lasted for n days, during each day the tourist noted height above the sea level

Codeforces 57C Array dp暴力找规律

题目链接:点击打开链接 先是计算非递增的方案, 若非递增的方案数为x, 则非递减的方案数也是x 答案就是 2*x - n 只需求得x即可. 可以先写个n3的dp,然后发现规律是 C(n-1, 2*n-1) 然后套个逆元即可. #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll long long #def

Codeforces 432E Square Tiling(构造+贪心)

我们通常这么写 using (SqlDataReader drm = sqlComm.ExecuteReader()) { drm.Read();//以下把数据库中读出的Image流在图片框中显示出来. MemoryStream ms = new MemoryStream((byte[])drm["Logo"]); Image img = Image.FromStream(ms); this.pictureBox1.Image = img; } 我的写数据 private void b

Codeforces 57B Martian Architecture 暴力||线段树

题目链接:点击打开链接 题意:n长的序列(初始全为0) m个操作 k个查询 下面m个操作[l,r] h 代表 a[l] +=h; a[l+1] += h+i; a[l+i] += h+i;  l<=i<=r 然后问k个位置的和 因为k<=100 所以直接暴力也可以 ----------------------- 如果k<=100000 也是可以做的 只需要给区间记录一个标记lazy,表示从左端点开始 l, l+1, l+i ··· l+r 而向下更新时, 左区间则直接更新, 右区间

Post Lamps CodeForces - 990E(暴力出奇迹?)

题意: 在一个从0开始的连续区间上  放置几个小区间,使得这些小区间覆盖整个大区间,不同长度的小区间有不同的花费,其中有m个点,小区间的左端点不能放在这些点上 解析: 显然如果0是这m点中的一个 则无解 然后就是标记上连续不能放的点  然后遍历每一个小区间  从0开始放 求花费最小值即可 · 注意最大值的设置 代码都加了1,从1开始 #include <bits/stdc++.h> using namespace std; const int maxn = 2000006, INF = 0x7

【CodeForces 990E】Post Lamps

传送门戳这里 Luogu & CodeForces 题目描述 Adilbek's house is located on a street which can be represented as the OX axis. This street is really dark, so Adilbek wants to install some post lamps to illuminate it. Street has nn positions to install lamps, they co

暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry

C. Amr and Chemistry Problem's Link: http://codeforces.com/problemset/problem/558/C Mean: 给出n个数,让你通过下面两种操作,把它们转换为同一个数.求最少的操作数. 1.ai = ai*2 2.ai = ai/2 (向下取整) analyse: 基本思路:首先枚举出每个数能够到达的数字并且记录下到达该数组需要的步数,然后从到达次数为n次的数字中选择步数最小的即为答案. 对于一个数字Ai,它可以变换得到的数字可

Codeforces 734C [水][暴力][贪心]

题意: 要生产n个物品,每个花费时间为x. 有两种魔法,每种最多使用1个. 其中第一种魔法可以使每个物品生产的花费时间变为ai,相应的花费是bi;第二种魔法可以减少ci个物品,相应的花费是di,并且保证对于i<j ci<=cj 且 di<=dj; #include<bits/stdc++.h> using namespace std; long long b[200050],c[200050],d[200050]; pair<long long ,long long&g