18.8.30考试总结
这道题明明很简单!!!!! 但是由于我的智商和wans_的智商打架了 受了重伤 所以就变笨了
看到题目之后很容易发现两个性质
1.不管这些球球怎么弹弹弹 他们的相对位置是不会变的
2.两个球碰撞之后互相反向 但是实际上相当于他们互相继承了对方的意志 去完成对方的使命
也就是说如果某一个球一开始在a位置向左走 a秒之后就会有一个球从左端点掉下去 不管这个是不是原来的球球
所以可以得到球从左端点和右端点掉下去的时间 再根据他们的相对位置排回原来的标号
代码
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int n,l,a[N],c1[N],c2[N],tot1,tot2,d[N]; int main( ) { freopen("ant.in","r",stdin); freopen("ant.out","w",stdout); scanf("%d%d",& l,& n); for(int i = 1;i <= n;i ++) scanf("%d",& a[i]); for(int i = 1;i <= n;i ++) { scanf("%d",& d[i]); if(d[i] == 0) { c1[++ tot1] = a[i]; } else c2[++ tot2] = l - a[i]; } sort(c1 + 1,c1 + tot1 + 1); sort(c2 + 1,c2 + tot2 + 1); for(int i = 1;i <= tot1;i ++) printf("%d.00 ",c1[i]); for(int i = tot2;i >= 1;i --) printf("%d.00 ",c2[i]); }
这道题就是一道原题嘛 之前我都有写过总结应该
因为想要操作次数最少 也就是剩余的花朵最多
$ dp[i] $ 表示选择1 ~ i的区间所能够剩余的最多单调不降的花朵的数量
然后用辅助数组 $ h[i] $ 表示 $ dp[i ]$ 对应的最后一个的高度 转移是很好理解的 就是枚举决策点 后面一段全部合并来转移dp
乱搞搞就可以了
代码
#include <bits/stdc++.h> using namespace std; const int N = 5 * 1e3 + 5; int dp[N],h[N],sum[N],a[N],n; int main( ) { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%d",& n); for(int i = 1;i <= n;i ++) { scanf("%d",& a[i]); sum[i] = sum[i - 1] + a[i]; } for(int i = 1;i <= n;i ++) { for(int j = 1;j <= i;j ++) { int s = sum[i] - sum[j - 1]; if(s >= h[j - 1] && dp[i] < dp[j - 1] + 1) { dp[i] = dp[j - 1] + 1; h[i] = s; } else if(s >= h[j - 1] && dp[i] == dp[j - 1] + 1) { h[i] = min(h[i],s); } } } printf("%d",n - dp[n]); }
这道题可以说是很简单了 二分答案 + 贪心check 然后就完了
其实可以O(n)check的 思路跟我是一样的 都是差分 但是我爱树状数组...!!就这样
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 3; int n,k; ll a[N],del[2 * N],t; ll lowbit(ll a) { return a & (-a); } ll query(int pos) { ll ans = 0; while(pos >= 1) { ans += del[pos]; pos -= lowbit(pos); } return ans; } void add(int pos,ll d) { while(pos <= n) { del[pos] += d; pos += lowbit(pos); } } bool check(ll len) { ll c = t; memset(del,0,sizeof(del)); for(int i = 1;i <= n;i ++) { ll delt = query(i); if(a[i] + delt >= len) continue; else { ll dd = len - a[i] - delt; c -= dd; if(c < 0) return false; add(i,dd); add(i + k,-dd); } } return true; } void solve( ) { ll l = 1,r = 2 * 1e9; ll ans = 0; while(l <= r) { ll mid = (l + r) >> 1; if(check(mid)) ans = mid,l = mid + 1; else r = mid - 1; } printf("%I64d",ans); } int main( ) { freopen("watering.in","r",stdin); freopen("watering.out","w",stdout); scanf("%d%d%I64d",& n,& k,& t); for(int i = 1;i <= n;i ++) scanf("%I64d",& a[i]); solve( ); }