昨晚真的自闭。。
C. Platforms Jumping
题意:n宽的河,m块木板,每个木板宽ci,这个人一次最远可以跳d远,问有没有可能这个人可以到达对岸(n+1处),并输出可行方案(1~n每块是水面(0),还是有第i块木板覆盖(i))。
统计木板总长数,如果木板长度加上 d * 跳的步数还是小于n,不可能到达对岸了。
否则开始贪心的放木板,这里有个值得注意的点就是,贪心贪过了最后木板出现重叠怎么办,
所有贪的时候还要注意,当前可跳过的水面总数是n-sum,贪心的同时加上这个约束条件,每次减去已跳过的水面数即可。
int main() { ll n, m, d; rd(n),rd(m),rd(d); ll c[m],sum = 0; for(int i = 0; i < m; i++) rd(c[i]),sum += c[i]; if(sum + (d - 1) * (m + 1) < n) { cout << "NO\n"; return 0; } cout << "YES\n"; ll z = n - sum;//空了多少水面w int a[n] = {0}; int pos = 0; for(ll i = 0; i < m; i++) { pos += min(d - 1, z);//每次贪心跳过最多可使用的空水面 for(ll j = pos; j - pos < c[i]; j++) a[j] = i + 1; z -= min(z, d - 1); pos += c[i]; } for(int i = 0; i < n; i++) cout << a[i] << ' '; return 0; }D. Binary String Minimizing
题意:可以交换最多k次相邻数字,问你最后能得到的字典序最小的字符串
例:
8 5 11011010 01011110对于某组交换的结果,肯定是一个0跨越一串1到达这一串1的尽量左侧,
所有考虑交换时只考虑0要和前面哪个1交换(0插到这一串1的最左侧还是插到1中间某位置)而不是挨个swap。(因为题目只有0和1,每个1都是等价的,所有0和这串1的哪个都可以直接换)
每次记录当前0之前的一串1的最左侧位置在哪里。
这种写法就比较神奇。
两种情况,可以到达最左侧。
11110 ——> 01111,新的最左侧肯定是原来的j+1
第二种情况,无法到达最左侧
11110 ——>11011,那么再之后一次也不能换了,这时候 j 在哪都无所谓了。
关键在于想到维护此刻0前一整串1的最左侧
int main () { int t;rd(t); while (t--) { ll n,k;rd(n),rd(k); string str;cin>> str; ll j = 0; for (ll i = 0; i < n; i++) { if(str[i] == '0') { ll l = min(i - j, k); swap(str[i], str[i - l]); k = k - l; j++; } } cout << str << "\n"; } }