A.Sort the Subarray
题意:给出一个数组,一个在此基础上被操作过的数组,找出被操作过的最长的非递减连续序列。
题解:这道题最开始写就被给的样例迷惑了,给出的样例都是被操作过出现非递减序列的片段,因此我就直接去看第二个数组,找它的最长非递减连续序列了。但是题意中还有提到一层意思,如果找出的非递减序列没被操作过,就不能作为答案。所以不能但看第二个数组,还要比对第一个数组找出被操作的地方,再找其中的最长非递减序列。
代码:
import java.util.ArrayList;
import java.util.Scanner;
public class A {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
int tt=0;
while(t>0) {
t--;
tt++;
int n = cin.nextInt();
ArrayList<Integer> a = new ArrayList();
ArrayList<Integer> b = new ArrayList();
for(int i=0; i<n; i++) {
int x = cin.nextInt();
a.add(x);
}
for(int i=0; i<n; i++) {
int x = cin.nextInt();
b.add(x);
}
if(tt==23) {
System.out.println(n);
for(int i=0;i<n;i++)System.out.println(a.get(i)+" "+b.get(i));
break;
}
int l=-1,r=-1;
int ll=-1,rr=-1;
int flag=0,cnt=0,ans=0;
for(int i=0; i<n-1; i++) {
int aa = b.get(i);
int bb = b.get(i+1);
if(aa <= bb) {
cnt++;
if(a.get(i)!=b.get(i)) {
flag=1;
}
if(cnt==1) {
l=i+1;
}
if(i==n-2) {
if(cnt>ans && flag==1) {
ll = l;
rr = i+2;
ans=cnt;
}
}
}else if(aa > bb){
if(cnt>ans && flag==1) {
ll = l;
rr = i+1;
ans=cnt;
}
// System.out.println(aa+ " " + bb + " " +ll + " " + rr);
cnt=0;
flag=0;
}
}
System.out.println(ll + " " + rr);
}
}
}
B.Tear It Apart
题意:对给出的字符串进行k次删除操作,每次操作删掉n个不相邻的字符,使得最后只剩下一种字母。求k的最小次数。
题解:这里我先找出给出字符串中出现过的字符,然后根据出现过的字符来找出它和它下一次出现时中间其他字符的个数,找出最大值就能求出留下这个字符所需操作的最小次数。然后依次将字符串中所有字符遍历。
代码:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class B {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
String s = cin.next();
int len = s.length();
Map<Character,Integer> mp = new HashMap<>();
int []p = new int[10005];
for(char i:s.toCharArray()) {
if(mp.containsKey(i)){ //key存在
Integer value = mp.get(i);
value++;
mp.put(i,value);
}else{ //key不存在
mp.put(i,1);
}
}
int minn=Integer.MAX_VALUE,cnt=0,sum=0;
Character ms = new Character('a');
for(Character key: mp.keySet()) {
Integer val = mp.get(key); //出现次数
// System.out.println(key + ": " + val);
cnt=0;
for(int i=0; i<len; i++) {
// System.out.println(s.charAt(i) +" " + ms);
if(s.charAt(i)==key){
cnt=0;
}else{
cnt++;
}
// System.out.println(s.charAt(i) +" " + cnt);
sum = Math.max(sum, cnt);
}
cnt=0;
while(sum>0) {
if(sum%2==1) {
sum = (sum-1)/2;
cnt++;
}else {
sum /= 2;
cnt++;
}
}
minn = Math.min(cnt, minn);
}
System.out.println(minn);
}
cin.close();
}
}
C.Yura's New Name
题意:^^或者^_^是笑脸,每次只能插入一个^或者_,求最小插入次数。
题解:先遍历中间连续的_,连续n个则中间插入n-1个^,特判第一个和最后一个,还要特判一下只有一个字符的时候。
代码:
import java.util.Scanner;
public class C {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
String s = cin.next();
int len = s.length();
int cnt=0,k=0;
if(len==1) {
if(s.charAt(0)=='^') {
cnt=1;
}else if(s.charAt(0)=='_') {
cnt=2;
}
}else if(len==2 && s.charAt(0)=='_' && s.charAt(1)=='_'){
cnt=3;
}else {
for(int i=1; i<len-2; i++) {
if(s.charAt(i)=='_' && s.charAt(i+1)=='_') {
k++;
}else if(s.charAt(i)=='_' && s.charAt(i+1)=='^') {
cnt+=k;
k=0;
}
}
cnt+=k;
// System.out.println(cnt);
if(s.charAt(0)=='_') {
if(s.charAt(1)=='^') {
cnt++;
}else {
cnt+=2;
// System.out.println("****");
}
}
if(s.charAt(len-1)=='_') {
if(s.charAt(len-2)=='^') {
cnt++;
}else {
cnt+=2;
// System.out.println("++++");
}
}
}
System.out.println(cnt);
}
}
}
D. JoJo's Incredible Adventures
题意:
题解:
代码:
import java.util.Scanner;
public class D {
public static void main(String[] args) throws Exception {
Scanner cin=new Scanner(System.in);
int t=cin.nextInt();
cin.nextLine();
while(t-->0) {
String s=cin.nextLine();
int i=0,j=s.length()-1;
if(!s.contains("0")){
long ans= (long) s.length() *s.length();
System.out.println(ans);
}
else{
long cnt=0,cnt1=0;
while(s.charAt(i)=='1'){
i++;
cnt++;
}
while(s.charAt(j)=='1'){
j--;
cnt1++;
}
int l=i+1,r=i+1;
long len=0;
for(;r<=j;){
if(s.charAt(r)=='1') r++;
else{
len=Math.max(len,r-l);
r++;
l=r;
}
}
len=Math.max(len,r-l);
len=Math.max(len,cnt+cnt1);
long ans=0,p=1,q=0;
while(p<=len){
q=p*len;
ans=Math.max(q,ans);
p++;
len--;
}
System.out.println(ans);
}
}
}
}
E. Constructive Problem
题意:
题解:
代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class E {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
int n = cin.nextInt();
ArrayList<Integer> a = new ArrayList<>();
Map<Integer,Integer> mp = new HashMap<>();
int cnt=0;
for(int i=0; i<n; i++) {
int x = cin.nextInt();
a.add(x);
// System.out.println(mp.get(x));
if(mp.get(x)==null||mp.get(x)==0) {
cnt=1;
}else {
cnt = mp.get(x)+1;
}
if(cnt==1)
mp.put(x, cnt);
else
mp.replace(x, cnt);
}
int mex=-14;
for(int i=0; i<n; i++) {
if(mp.get(i)==null||mp.get(i)==0) {
mex=i;
break;
}
}
int m = mex+1;
int be=-1,en=-1;
int f1=0,f2=0;
for(int i=0; i<n; i++) {
if(a.get(i)==m && f1==0) {
be = i;
f1=1;
}
if(a.get(n-1-i)==m && f2==0) {
en = n-i-1;
f2=1;
}
if(f1==1 && f2==1) break;
}
if(be!=-1||en!=-1) {
for(int i=be; i<=en; i++) {
int val = a.get(i);
int now = mp.get(val)-1;
mp.replace(val,now);
// System.out.println(val+ ": "+now);
}}
//if(mex<=n-1) {
mp.put(mex, 1);
//}
int newMex=-10;
for(int i=0; i<=n; i++) {
// System.out.println(i+" "+mp.get(i));
if(mp.get(i)==null || mp.get(i)==0) {
newMex=i;
break;
}
}
// System.out.println(m+" "+newMex);
if((newMex!=m||mex==n)) {
System.out.println("No");
}else {
System.out.println("Yes");
}
}
}
}
F.Li Hua and Maze
题意:划掉最少的点,使得给出的起始位置走不到终点。
题解:特判四个点和除去点以外的边需要的点。
代码:
import java.util.Scanner;
// F - Li Hua and Maze
public class F {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
int n = cin.nextInt();
int m = cin.nextInt();
int x1 = cin.nextInt();
int y1 = cin.nextInt();
int x2 = cin.nextInt();
int y2 = cin.nextInt();
int cnt=0;
if((x1==1 && y1==1) || (x1==n && y1==1) || (x1==1 && y1==m) || (x1==n && y1==m)) {
cnt=2;
}else if((x2==1 && y2==1) || (x2==n && y2==1) || (x2==1 && y2==m) || (x2==n && y2==m)) {
cnt=2;
}else if((x1==1 && y1!=1 && y1!=m) || (x2==1 && y2!=1 && y2!=m)) {
cnt=3;
}else if((y1==1 && x1!=1 && x1!=n) || (y2==1 && x2!=1 && x2!=n)) {
cnt=3;
}else if((x1==n && y1!=1 && y1!=m) || (x2==n && y2!=1 && y2!=m)) {
cnt=3;
}else if((y1==m && x1!=1 && x1!=n) || (y2==m && x2!=1 && x2!=n)) {
cnt=3;
}else if(x1!=1 && x2!=1 && y1!=1 && y2!=1) {
cnt=4;
}
System.out.println(cnt);
t--;
}
cin.close();
return ;
}
}
G.Li Hua and Pattern
题意:给出长度为n的数组,可以做出k个操作,将二维数组翻转180°让它和原来长的一样。
题解:先找出旋转以后与原来颜色不一样的个数cnt,每次操作可以换一个颜色k-1。
如果k<cnt的话,显然长的不一样。
如果k>=cnt时,k为奇数则分为两种情况:
1. n为奇数时,则k可以变换最中间的点,那么对称。
2. n为偶数时,则不能满足题意,怎么变都不一样。
k为偶数则怎么变都满足题意。
代码:
import java.util.Scanner;
public class G {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
int n = cin.nextInt();
int k = cin.nextInt();
int [][]a = new int[1005][1005];
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
int x = cin.nextInt();
a[i][j] = x;
}
}
int cnt=0;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
// System.out.println(a[i][j] + " " + a[n-i-1][n-j-1]);
if(a[i][j] != a[n-i-1][n-j-1]) {
cnt++;
}
}
}
// System.out.println(cnt);
cnt /= 2;
int flag=1;
if(k>=cnt) {
int ans = k-cnt;
if(ans%2!=0 && n%2==0) {
flag=0;
}
}else {
flag=0;
}
if(flag==0) {
System.out.println("NO");
}else {
System.out.println("YES");
}
//这样写会时间超限,不能有太多if/else
// if(k>=cnt) {
// int ans = k-cnt;
// if(ans%2==0) {
// System.out.println("YES");
// }else {
// if(n%2==0) {
// System.out.println("NO");
// }else {
// System.out.println("YES");
// }
// }
// }else {
// System.out.println("NO");
// }
}
}
}
I. Lucky Numbers
题意:
题解:
代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class I {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
int []g = new int[10];
ArrayList<Integer> list = new ArrayList<>();
list.add(-1);
for(int i=1; i<=1000000; i++) {
int k=0,r=i;
while(r!=0) {
g[k] = r%10;
r/=10;
k++;
}
int a=Integer.MIN_VALUE,b=Integer.MAX_VALUE;
for(int j=0; j<k; j++) {
// System.out.println(g[j]);
a = Math.max(g[j], a);
b = Math.min(g[j], b);
}
// System.out.println(a+" " + b);
int c = Math.abs(a-b);
list.add(c);
}
while(t>0) {
t--;
int n = cin.nextInt();
int m = cin.nextInt();
int maxx = -1, sum=0;
Map<Integer,Integer> mp = new HashMap<>();
if(n<10 && m>=10) {
n=10;
}
if((m-n)<100) {
for(int i=n; i<=m; i++) {
mp.put(list.get(i), i);
maxx = Math.max(maxx,list.get(i));
}
System.out.println(mp.get(maxx));
}else {
int y = n%100; //最后两位
int x = (n/100)%10; //倒数第三位
int z = n/1000; //从第一个数字到倒数第四位
// System.out.println(z + " " + x + " "+ y);
if(y>9) {
int jw = (x+1)/10;
int p = z%10; //倒数第四位开始逐个往前缩进
if(jw==0) { //不需要进位
sum = (z*10+x+1)*100+9;
}else { //需要进位
sum += (x+1)%10*100+9;
int bs = 1000;
while(z>0) {
p += jw;
jw = p/10;
x = p%10;
sum += x*bs;
bs *= 10;
// System.out.println(z + " " + sum + " " +jw);
z /= 10;
p = z%10;
}
if(z==0 && jw!=0) {
sum += jw*bs;
}
}
}else {
sum = (z*10+x)*100+9;
}
System.out.println(sum);
}
}
}
}
J.Playing in a Casino
题意:给出n个长度为m的数组,让求出排列组合后每组根据给出公式求出结果的和。
题解:先找出所有两两一组的结果,然后根据每组顺序套公式求出结果相加。
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Arrays;
import java.util.Collections;
public class J {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
long n = cin.nextInt();
long m = cin.nextInt();
ArrayList<ArrayList<Long>> re = new ArrayList<>();
ArrayList<Integer> b = new ArrayList<>();
ArrayList<Long> last = new ArrayList<>();
for(int i=0; i<n; i++) {
ArrayList<Long> row = new ArrayList<>();
b.add(i);
for(int j=0; j<m; j++) {
long x = cin.nextInt();
row.add(x);
}
re.add(row);
if(i==0) {
last.add(n-1);
}else if(i>0 && i!=n-1) {
long r = i+1;
long now = last.get(i-1)-(r-1)+n-r;
// System.out.println(now);
last.add(now);
}
}
ArrayList<ArrayList<Long>> fz = new ArrayList<>();
long sum=0,cnt=0;
for(int i=0; i<m; i++) {
ArrayList<Long> lie = new ArrayList<>();
for(int j=0; j<n; j++) {
// System.out.print(re.get(j).get(i) + " ");
lie.add(re.get(j).get(i));
}
Collections.sort(lie);
// System.out.println(lie);
fz.add(lie);
for(int j=0; j<n-1; j++) {
cnt = fz.get(i).get(j+1) - fz.get(i).get(j);
sum += cnt * last.get(j);
}
}
System.out.println(sum);
}
}
}
扩展:
用 ArrayList 创建动态二维数组:
import java.util.ArrayList;
import java.util.List;
public class I {
public static void main(String []args) {
//创建一个二维数组
List<List<Integer>> re = new ArrayList<List<Integer>>();
//增加元素
//添加行
List<Integer> listRow = new ArrayList<>();
listRow.add(1);
listRow.add(3);
listRow.add(5);
listRow.add(7);
listRow.add(9);
//把行添加到二维数组
re.add(listRow);
//添加列
List<Integer> listColumn = new ArrayList<>();
listColumn.add(0);
listColumn.add(2);
listColumn.add(4);
listColumn.add(6);
listColumn.add(8);
re.add(listColumn);
System.out.println(re);
for (int i = 0; i < re.size(); i++) {
for (int j = 0; j < ((ArrayList) re.get(i)).size(); j++) {
String str = ((ArrayList) re.get(i)).get(j).toString();
System.out.print(str + " ");
}
System.out.println("");
}
}
}
输出:
注意:向动态二维数组内添加行,要在第一层循环内定义,保证更新不同的ArrayList,否则就会出现都加到同一行的情况。
错误的:
正确的:
求一组数两两组合的所有结果:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Arrays;
public class J {
public static void main(String []args) {
List<Integer> mylist = Arrays.asList(1,2,3);
//Map<Integer, Integer> mymap = new HashMap<Integer, Integer>();
List<String> list = new ArrayList<String>();
for(int i=0;i< mylist.size()-1;i++)
{
for(int j=i+1;j< mylist.size();j++)
{
list.add(mylist.get(i)+":"+mylist.get(j));
}
}
for(int k = 0; k< list.size(); k++)
{
System.out.println(list.get(k));
}
}
}
输出:
K. Showstopper
题意:
题解:
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class I {
public static void main(String []args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t>0) {
t--;
int n = cin.nextInt();
int []a = new int[105];
int []b = new int[105];
for(int i=0; i<n; i++) {
int x = cin.nextInt();
a[i] = x;
}
for(int i=0; i<n; i++) {
int x = cin.nextInt();
b[i] = x;
}
int maxx = Math.max(a[n-1], b[n-1]);
int flag=1;
for(int i=0; i<n-1; i++) {
if(maxx<a[i] || maxx<b[i]) {
flag=0;
}
}
if(maxx==a[n-1]) {
for(int i=n-2; i>=0; i--) {
if(b[i]>b[n-1] && a[i]>b[n-1]) {
flag=0;
}
}
}else if(maxx==b[n-1]){
for(int i=n-2; i>=0; i--) {
if(a[i]>a[n-1] && b[i]>a[n-1]) {
flag=0;
}
}
}
if(flag==0) {
System.out.println("No");
}else {
System.out.println("Yes");
}
}
}
}
L. Three Sevens
题意:
题解:
代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class L {
public static void main(String []args) {
Scanner scanner=new Scanner(System.in);
int t=scanner.nextInt();
while(t-->0) {
int m=scanner.nextInt();
HashMap<Integer,Integer> playerDay=new HashMap<>(5000);//key为玩家编号,value为天数
for(int i=1;i<=m;i++){
int n=scanner.nextInt();
for(int j=1;j<=n;j++){
int x=scanner.nextInt();
playerDay.put(x,i);//存储玩家可能获奖的最近的那一天
}
}
List<Integer>ans=new ArrayList<>();
HashMap<Integer,Integer> dayPlayer=new HashMap<>(5000);//key为玩家编号,value为天数
// 构建 value-key 映射
for (Map.Entry<Integer, Integer> entry : playerDay.entrySet()) {
dayPlayer.put(entry.getValue(), entry.getKey());
}
for(int i=1;i<=m;i++){//遍历每一天
if(dayPlayer.get(i)!=null)ans.add(dayPlayer.get(i));
}
if(ans.size()<m) System.out.println(-1);
else{
for (int i = 0; i < m; i++) {
System.out.print(ans.get(i)+" ");
if(i==m-1) System.out.println();
}
}
}
}
}
M. Candy Store
题意:
题解:
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=2e5+10;
ll a[N],b[N];
ll s[N];
int main()
{
//cout<<2%3<<endl;
ll t,n;
cin>>t;
int cnt=0;
while(t--)
{
cnt++;
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>a[i]>>b[i];
s[i]=a[i]*b[i];
}
ll ans=n,x=0,g=s[1],l=b[1];
for(int i=2; i<=n; i++)
{
g=__gcd(g,s[i]);
ll tt=__gcd(l,b[i]);
l=b[i]*l/tt;
//cout<<g<<" "<<l<<endl;
if(g%l==0){
ans--;
}else{
g=s[i];
l=b[i];
}
}
cout<<ans<<'\n';
}
}
//3213112