目录
D. Pinball:
题目大意:
思路解析:
代码实现:
代码一:
代码二:
D. Pinball:
题目大意:
思路解析:
假设字符串为 >>><<<, 当前位置为第四位, 那我们可以想到我们如果处在 < 这个位置上,那我们应该找到左边第一个 > 位置,位移到了>位置后,我们应该找到右边第一个 <位置,每次经过的点 > 会改变为 <, > 会改变为 <,如果这样修改肯定是复杂的,我们可以利用双指针来寻找,这样就可以省略中间将 > 修改为 < 和 < 修改为 > 的过程,但是如果出现字符串形如 <><><><>这样的双指针每次只能移动个位置,然后时间复杂度任然会退化为O(N*N)的时间复杂度。 (参考代码一)
那我们可以发现上诉的分析过程中,我们每次只需要找到<>这两个位置,那我们想到是否可以利用前缀和来求解。
假设字符串为 ><<>><,现在处于 i == 4的位置, 那么答案为 (6 - 4) + (6 - 1) + (7 - 1) 等价于 2 * (6 - 4 - 1) + 4 + (6 + 1),我们可以发现 6 是一个前缀和,(4+1)也是一个前缀和,貌似看作为前缀和很合理,然后再结合第一个思想和举几个例子验证,发现确实可以利用前缀和假设 (参考代码二)
代码实现:
代码一:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static int inf = (int) 2e7;
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
w.println();
t--;
}
w.flush();
w.close();
br.close();
}
static int maxN = (int) 1e6 + 5;
static int N = (int) 1e6;
public static void solve() {
int n = f.nextInt();
char[] s = (" " + f.next()).toCharArray();
int[][] l = new int[n+2][2];
int[][] r = new int[n+2][2];
r[n+1][0] = n + 1; r[n+1][1] = n+1;
for (int i = 1; i <= n; i++) {
if (s[i] == '>'){
l[i][0] = i;
l[i][1] = l[i-1][1];
}else {
l[i][1] = i;
l[i][0] = l[i-1][0];
}
}
for (int i = n; i >= 1; i--) {
if (s[i] == '>'){
r[i][0] = i;
r[i][1] = r[i+1][1];
}else {
r[i][1] = i;
r[i][0] = r[i+1][0];
}
}
// 0 > 1 <
for (int i = 1; i <= n; i++) {
int p = i, q = i;
int op = 0;
int ned = 0;
if (s[i] == '>'){
op = 1;
ned = 1;
}
long ans = 0;
while (!(p == 0 || q == n + 1)){
if (op == 1){
if (q == r[q][ned]) q++;
q = r[q][ned];
ans += q - p;
ned ^= 1;
op = 0;
}else {
if (p == l[p][ned]) p--;
p = l[p][ned];
ans += q-p;
ned ^= 1;
op = 1;
}
}
w.print(ans + " ");
}
}
public static class Node{
int l,r;
int[] sum = new int[2];
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}
代码二:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static int inf = (int) 2e7;
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
w.println();
t--;
}
w.flush();
w.close();
br.close();
}
static int maxN = (int) 1e6 + 5;
static int N = (int) 1e6;
static int[] cntR;
static int[] cntL;
static long[] sumR;
static long[] sumL;
static int n;
public static void solve() {
n = f.nextInt();
char[] s = (" " + f.next()).toCharArray();
cntL = new int[n+1];
cntR = new int[n+1];
sumL = new long[n+1];
sumR = new long[n+1];
for (int i = 1; i <= n; i++) {
cntL[i] = cntL[i - 1];
cntR[i] = cntR[i - 1];
sumL[i] = sumL[i - 1];
sumR[i] = sumR[i - 1];
if (s[i] == '>'){
cntR[i]++;
sumR[i] += i;
}else {
cntL[i]++;
sumL[i] += i;
}
}
for (int i = 1; i <= n; i++) {
if (s[i] == '>'){
if (cntR[i] > cntL[n] - cntL[i]){
int p = getpre(cntR[i] - (cntL[n] - cntL[i]));
w.print(2 * ((sumL[n] - sumL[i]) - (sumR[i] - sumR[p-1])) + n + i + 1);
w.print(" ");
}else {
int p = getsuf((cntL[n] - cntL[i]) - cntR[i]);
w.print(2 * ((sumL[p] - sumL[i-1]) - sumR[i]) + i);
w.print(" ");
}
}else {
if (cntL[n] - cntL[i-1] > cntR[i]){
int p = getsuf((cntL[n] - cntL[i-1]) - cntR[i] - 1);
w.print(2 * ((sumL[p] - sumL[i-1]) - sumR[i]) - i);
w.print(" ");
}else {
int p = getpre(cntR[i] - (cntL[n] - cntL[i-1]) + 1);
w.print(2 * ((sumL[n] - sumL[i - 1]) - (sumR[i] - sumR[p - 1])) + (n+1) - i);
w.print(" ");
}
}
}
}
public static int getpre(int x){
int l = 1, r = n;
int res = 0;
while (l <= r){
int m = (l + r) >> 1;
if (cntR[m] >= x){
r = m - 1;
res = m;
}else {
l = m + 1;
}
}
return res;
}
public static int getsuf(int x){
int l = 1, r = n;
int res = 0;
while (l <= r){
int m = (l + r) >> 1;
if (cntL[n] - cntL[m] <= x){
res = m;
r = m - 1;
}else {
l = m + 1;
}
}
return res;
}
public static class Node{
int l,r;
int[] sum = new int[2];
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}