牛客练习赛10

牛客练习赛10

旅游观光

代码

#include <bits/stdc++.h>

using namespace std;

int main()
{
  int n;
  cin >> n;
  cout << (n - 1) / 2 << endl;

  return 0;
}

栈和排序

我们用mx倒着记录max(a[i+1],a[i])
然后,正着扫一遍,如果当前元素小于等于mx[i]的话,我们就将他放到栈内,如果大于mx[i]的话,就先放到栈内,然后在取出来。
解释:
我们正着看的时候,遇到每个字符不知道什么时候该输出,但是,我们想让大的先输出,小的后输出。这样才能让字典序尽可能的大。
那我们来看,如果当前元素比后面的所有元素都大的话,是不是就该输出了呢,这显然是对的。
这样,贪心的走出来,每一步都尽可能的让字典序最大,那整体来看也是最大的。

import java.util.*;
import java.io.*;

public class Main{
	public static int[] solve(int[] a){
		int n = a.length;
		Stack<Integer> s = new Stack<Integer>();
		
		int ct = 0;
		int[] res = new int[n];
		int[] mx = new int[n + 1];
		
		for (int i = n - 1; i >= 0; i -- ){
			mx[i] = Math.max(mx[i + 1], a[i]);
		}
		
		for (int i = 0; i < n; i ++ ){
			int num = a[i];
			if (num <= mx[i + 1])
				s.push(num);
			else {
				res[ct ++ ] = num;
				while (!s.isEmpty() && s.peek() > mx[i + 1]){
					res[ct ++ ] = s.pop();
				}
			}
		}
		
		return res;
	}
	
	public static void main(String[] args){
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] nums = new int[n];
		for (int i = 0; i < n; i ++ ) {
			nums[i] = in.nextInt();
		}
		
		int[] res = solve(nums);
		System.out.print(res[0]);
		for (int i = 1; i < n; i ++ ){
			System.out.print(" " + res[i]);
		}
	}
}

最长回文

这个题,需要好好记住,一个好题。
我们给字符串扩充#后,i和j坐标,一个在前指着字符串A,一个在后两个位置处(因为有#),每次从当前i]向后扩展p[i] + cnt位,j向前扩展。记录最大匹配, 最后减一就是结果了。

#include <bits/stdc++.h>

using namespace std;

const int N = 400010;

int n;
char c[N], c1[N], c2[N];
int p1[N], p2[N];
int len;
void change(char *str);
void mannacher(char *str, int *p);
int query();

int main()
{
  cin >> n;
  len = n << 1 | 1;
  // cout << len << endl;
  mannacher(c1, p1);
  mannacher(c2, p2);
  printf("%d\n", query());
}

void change(char *str){
  scanf("%s", c);
  int ct = 0;
  str[ct ++ ] = '$';
  str[ct ++ ] = '#';
  for (int i = 0; i < n; i ++ )
  {
    str[ct ++ ] = c[i];
    str[ct ++ ] = '#';
  }
}

void mannacher(char *str, int *p)
{
  change(str);
  int id = 0, mx = 0, reslen = 0, rescentre = 0;
  for (int i = 1; i <= len; i ++ )
  {
    if (mx > i) p[i] = min(p[id * 2 - i], mx - i);
    else p[i] = 1;

    while (i - p[i] > 0 && str[i - p[i]] == str[i + p[i]]) p[i] ++;

    if (mx < i + p[i])
    {
      mx = i + p[i];
      id = i;
    }

    if (reslen < p[i])
    {
      reslen = p[i];
      rescentre = i;
    }
  }
}
int query() {
   int ans = 1;
   for(int i = 2; i <= len; i++) {
       int tmp = max(p1[i], p2[i - 2]);
       while(c1[i - tmp] == c2[i + tmp - 2]) tmp++;
       ans = max(ans, tmp);
   }
   return ans - 1;
}
// int query(){
//   int ans = 1;
//   for (int i = 2; i <= len; i ++ )
//   {
//     int tmp = max(p1[i], p2[i - 2]);
//     while (c1[i - tmp] == c2[i - 2 + tmp]) tmp ++;
//     // if (tmp == 4) puts("###########################");
//     // if (tmp == 5) puts("((((((((((((((((((((((((((");
//     // if (tmp == 6) puts("))))))))))))))))))))))))))");
//     // if (tmp == 7) puts("-------------------------");
//     // if (tmp == 9) puts("***************************");
//     // for (int j = i, s = tmp; s > 0; s --, j -- ) cout << c1[j];
//     // cout << endl;
//     // for (int j = i - 2, s = tmp; s > 0; s --, j ++ ) cout << c2[j];
//     // cout << endl;
//     // cout << "=====================" << endl;
//     ans = max(ans, tmp);
//     // int tmp = max(p1[i], p2[i + 2]);
//     // while (c1[i + tmp] == c2[i + 2 - tmp]) tmp ++;
//     // ans = max(ans, tmp);
//     if (tmp > len) break;
//   }

  // return ans - 1;
// }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值