贪心的分情况讨论:x没被禁,全1,x被禁,分情况讨论:
如果k<=1,无解。 k=2时奇数,无解。 k>2时,有解。
- void solve(){
- int n, k, x; cin >> n >> k >> x;
- if (x != 1){
- vi a(n, 1);print(yes); print(len(a));print(a);return;
- }
- else{
- if (k <= 1) {print(no); return;}
- else if (k == 2 && n & 1){print(no); return;}
- else { print(yes);
- vi a;
- while (n > 3) {a.pb(2); n-= 2;}
- a.pb(n == 2 ? 2 : 3);
- print(len(a));
- print(a);
- }
- }
- }
二维空间中三个点ABC,求BC到A的最短路径中的最长公共距离。问题等价于:求A到BC的路径中最长公共距离。
当B和C有公共距离时,A一定是满足这个条件:A在BC上或者下方,A在BC左或者右方,直接计算即可。
- void solve(){
- ll dis = 0;
- pi a, b, c; cin >> a.first >> a.second >> b.first >> b.second >>c.first >>c.second;
- if (a.first >= max(b.first, c.first)) {dis += a.first - max(b.first, c.first);}
- else if (a.first <= min(b.first, c.first)) {dis += min(b.first, c.first) - a.first;}
- //print(dis);
- if (a.second >= max(b.second, c.second)) {dis += a.second - max(b.second, c.second); }
- else if (a.second <= min(b.second, c.second)) {dis += min(b.second, c.second) - a.second;}
- print(dis + 1);
- }
最后dis+1是考虑了在a点汇合时的一个公共坐标
枚举字符串的时间复杂度是O(n * pow(m, 10)),必TLE。
于是问题转换为构造S中不出现的子串。
答案字符串的长度为m,对于0~m-1位置的字符,贪心地枚举每个位置上的字符的最远匹配距离。这个策略可以证明一定是最优解。
- void solve(){
- string s; cin >> s;
- int m; cin >> m;
- string t1, t2;cin >>t1 >> t2;
- int rb = 0;
- lfor (i, 0, m - 1){
- int r = 0;
- if(t1[i] > t2[i]) swap(t1[i], t2[i]);
- while (t1[i] <= t2[i]){
- int t = s.find(t1[i], rb);
- if(t==-1){print(yes); return;}
- t ++;
- r = max(r, t);
- t1[i] ++;
- }
- rb = max(rb, r);
- }
- print(no);
- }
在数组求前缀和的过程中找到一个k值,当前缀和在做减法运算时,可以让前缀和不低于k。求前缀和最大的情况下的k值。
贪心策略:可以发现为了让最终前缀和最大,需要消除掉在计算过程中对前缀和影响最大的负数。于是问题转化为,贪心查找数组中连续区间的最小值(值是负数),然后记录这个区间前面的前缀和,就是答案。
- void solve(){
- int n; cin >> n;
- vi a(n); liter(x, a) cin >> x;
- ll minn = 2e9;
- ll curmin = 0;
- ll sum = 0;
- ll ans = 0;
- ll presum = 0;
- lfor (i, 0, n - 1){
- curmin += a[i];
- if (cmin(minn, curmin)){ //全局最小值小于当前局部连续区间最小值
- ans = presum;
- }
- sum += a[i];
- if (cmin(curmin, 0ll)){ //当前局部连续区间最小值大于0,舍弃之前的区间,并记录当前的前缀和
- presum = sum;
- }
-
- }
- print(ans);
- }