1001. A+B Format
输出A+B,从低位到高位每三个数位用半角逗号分隔;直接模拟即可,可转换成字符串,也可以不断对10取模
public static void main(String[] args) throws Exception {
int a=in.readInt();
int b=in.readInt();
int ans=a+b,k=0;
Deque<Character> stack=new ArrayDeque<>();
String s=String.valueOf(abs(ans));
for(int i=s.length()-1;i>=0;i--){
stack.push(s.charAt(i));
k++;
if(k%3==0) stack.push(',');
}
if(stack.peek()==',') stack.pop();
if(ans<0) out.print('-');
while(!stack.isEmpty()){
out.print(stack.pop());
}
out.close();
}
1002.A+B for Polynomials
多项式加法,输出运算后有多少项和每一项的指数以及系数,注意按照样例依指数从大到小输出
,同时注意删除系数为0的项,可用map实现。
public static void main(String[] args) throws Exception {
n=in.readInt();
int exp=0;
double coe=0;
TreeMap<Integer,Double> map=new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
while(n-->0){
exp=in.readInt();
coe=in.readDouble();
map.merge(exp,coe,Double::sum);
}
m=in.readInt();
while(m-->0){
exp=in.readInt();
coe=in.readDouble();
map.merge(exp,coe,Double::sum);
if(map.get(exp)==0) map.remove(exp);
}
out.print(map.size());
for(int key:map.keySet()){
out.print(" "+key+" "+new DecimalFormat(".0").format(map.get(key)));
}
out.close();
}
1003.Emergency
给定一张无向图以及数点间的边权和各点点权,求给定两点间最短路径数量以及最短路径上的点权和的最大值
最短路Dijkstra,由于数据很小,朴素版和堆优化版均可以通过。难点在于如何求出最短路径数量。令cnt[u] 表示在当前得到u的最短路距离的路径条数,v为u的下一个节点。若此时到v的最短距离小于已记录最短距离,更新最短距离,且最短路径数一起更新,即cnt[v]=cnt[u];若此时最短距离等于已记录最短距离,则说明有新的最短路径,即cnt[v]+=cnt[u];注意初始化起点cnt为1.
static class edge{
int u,v,w;
public edge(int u, int v, int w) {
this.u = u;
this.v = v;
this.w = w;
}
}
static Vector<edge> e;
static Vector<Integer>[] h;
static int[] a,d,sum,cnt;
static boolean[] vis;
static void add(int u,int v,int w){
e.add(new edge(u,v,w));
h[u].add(e.size()-1);
}
static void Init(int n){
h=new Vector[n+10];
for(int i=0;i< h.length;i++) h[i]=new Vector<>();
e=new Vector<>();
a=new int[n+10];
d=new int[n+10];
vis=new boolean[n+10];
sum=new int[n+10];
cnt=new int[n+10];
}
static void Dijkstra(int s,int end){
Arrays.fill(d,0x3f3f3f3f);
Arrays.fill(vis,false);
PriorityQueue<int[]> p=new PriorityQueue<>((a,b)->(a[0]-b[0]));
d[s]=0;
cnt[s]=1;
p.offer(new int[]{0,s});
while(!p.isEmpty()){
int[] t=p.poll();
int u=t[1];
if(vis[u]) continue;
vis[u]=true;
for(int ed:h[u]){
int v=e.get(ed).v;
int w=e.get(ed).w;
if(d[u]+w<d[v]){
d[v]=d[u]+w;
p.offer(new int[]{d[v],v});
cnt[v]=cnt[u];
sum[v]=sum[u]+a[v];
}
else if(d[u]+w==d[v]){
cnt[v]+=cnt[u];
sum[v]=max(sum[v],sum[u]+a[v]);
}
}
}
}
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
int s=in.readInt();
int end=in.readInt();
Init(n);
for(int i=0;i<n;i++) a[i]=in.readInt();
for(int i=0;i<m;i++){
u=in.readInt();
v=in.readInt();
w=in.readInt();
add(u,v,w);
add(v,u,w);
}
sum[s]=a[s];
Dijkstra(s,end);
out.print(cnt[end]+" "+sum[end]);
out.close();
}
}
1004.Counting Leaves
给定一个森林的节点个数,以及各点的儿子,求各层次的叶子个数
可记录各层次的点,然后检查其是否有儿子
static void Init(int n){
h=new Vector[n+10];
dep=new Vector[n+10];
d=new int[n+10];
for(int i=0;i<h.length;i++) h[i]=new Vector<>();
for(int i=0;i<h.length;i++) dep[i]=new Vector<>();
}
static Vector<Integer>[] h,dep;
static int[] d;
static int maxDep=1;
static void getDep(int u){
for(int i=0;i<h[u].size();i++){
int v=h[u].get(i);
d[v]=d[u]+1;
maxDep=max(maxDep,d[v]);
dep[d[v]].add(v);
getDep(v);
}
}
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
Init(n);
while(m-->0){
int idx=in.readInt();
int cnt=in.readInt();
while(cnt-->0){
int kid=in.readInt();
h[idx].add(kid);
}
}
d[1]=1;
dep[1].add(1);
getDep(1);
for(int i=1;i<=maxDep;i++){
int cnt=0;
for(int j=0;j<dep[i].size();j++){
u=dep[i].get(j);
if(h[u].size()==0) cnt++;
}
if(i==1) out.print(cnt);
else out.print(" "+cnt);
}
out.close();
}
}
1005.Spell It Right
给出一数,对其所有数位上的数字求和,然会从高位到低位输出结果各数位数字的英文。
字符串读入,哈希表读取即可
public static void main(String[] args) throws Exception {
HashMap<Character,String> map=new HashMap<>(){{
put('0',"zero");put('1',"one");put('2',"two");
put('3',"three");put('4',"four");put('5',"five");
put('6',"six");put('7',"seven");put('8',"eight");
put('9',"nine");
}};
String s=in.readStringLine();
int sum=0;
for(int i=0;i<s.length();i++){
sum+=(s.charAt(i)-'0');
}
s=String.valueOf(sum);
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(i==0) out.print(map.get(ch));
else out.print(" "+map.get(ch));
}
out.close();
}
1006.Sign In and Sign Out
给定n个人的ID_number,到达和离开的时间,求最先到达和最后离开的人的ID_number。
字符串比较,自定义排序即可
public static void main(String[] args) throws Exception {
n=in.readInt();
String[][] str=new String[n][];
for(int i=0;i<n;i++) str[i]=in.readStringLine().split(" ");
String[][] copy=str.clone();
Arrays.sort(str, new Comparator<String[]>() {
@Override
public int compare(String[] o1, String[] o2) {
return o1[1].compareTo(o2[1]);
}
});
Arrays.sort(copy, new Comparator<String[]>() {
@Override
public int compare(String[] o1, String[] o2) {
return o2[2].compareTo(o1[2]);
}
});
out.print(str[0][0]+" "+copy[0][0]);
out.close();
}
1007.Maximum Subsequence Sum
给出n个数,输出最大子段和及左右边界;若有多个答案,输出最小下标的左右边界
最大子段和板子题,只需另外记录左右边界即可
public static void main(String[] args) throws Exception {
n=in.readInt();
int[] a=new int[n+1];
int f=0;
long ans=0,res=0,l=0,r=0,ansl=0,ansr=0;
for(int i=1;i<=n;i++){
a[i]=in.readInt();
if(a[i]>=0) f=1;
if(res>0) {
res+=a[i];
}
else{
l=a[i];
res=a[i];
}
if(res>ans){
ans=res;
r=a[i];
ansl=l;
ansr=r;
}
}
if(f==0) out.print(0+" "+a[1]+" "+a[n]);
else out.print(ans+" "+ansl+" "+ansr);
out.close();
}
1008.Elevator
简单模拟,注意上次与本次是同一楼层需要加5秒
public static void main(String[] args) throws Exception {
n=in.readInt();
int pre=0,cur=0,ans=0;
for(int i=1;i<=n;i++){
cur=in.readInt();
if(cur>pre) ans+=(cur-pre)*6+5;
else if(cur<pre) ans+=(pre-cur)*4+5;
else ans+=5;
pre=cur;
}
out.print(ans);
out.close();
}
1009.Product of Polynomials
模拟,多项式乘法,同1002,注意删除系数为0的项
public static void main(String[] args) throws Exception {
n=in.readInt();
int exp=0;
double coe=0;
TreeMap<Integer,Double> map=new TreeMap<>((o1,o2)->(o2-o1));
int[] a=new int[n];
double[] b=new double[n];
for(int i=0;i<n;i++){
a[i]=in.readInt();
b[i]=in.readDouble();
}
m=in.readInt();
while(m-->0){
exp=in.readInt();
coe=in.readDouble();
for(int i=0;i<n;i++){
map.merge(exp+a[i],coe*b[i],Double::sum);
}
}
Vector<Integer> v=new Vector<>();
for(int key:map.keySet()){
v.add(key);
}
for(int key:v){
if(map.get(key)==0) map.remove(key);
}
out.print(map.size());
for(int key:map.keySet()){
out.print(" "+key+" "+new DecimalFormat(".0").format(map.get(key)));
}
out.close();
}
1010.Radix
模拟,二分
k进制下,取模最大数字为k-1,所以目的串的最大数字加1即为操作串的最小进制,最大进制为目的串本身。但由于目的串在转换成十进制时可能非常大造成溢出变成负数,故最大进制为max(目的串本身,最小进制);找到进制范围后,二分即可。需要注意二分过程中若返回负数,代表此时选择的进制仍然较大,需要减小右边界。
static int getmaxdigit(String s){
int ans=0;
char ch;
for(int i=0;i<s.length();i++){
ch=s.charAt(i);
if(ch>'9') ans=max(ans,ch-'a'+10);
else ans=max(ans,ch-'0');
}
return ans;
}
static long f(String s,long radix){
long ans=0;
long p=1,x;
char ch;
for(int i=s.length()-1;i>=0;i--){
ch=s.charAt(i);
if(ch>'9') x=ch-'a'+10;
else x=ch-'0';
ans+=x*p;
p*=radix;
if(ans<0) return -1;//溢出
}
return ans;
}
public static void main(String[] args) throws Exception {
String a=in.readString();
String b=in.readString();
int tag=in.readInt();
int radix=in.readInt();
if(tag==2){
String s=b;
b=a;
a=s;
}
long des=f(a,radix);
long l=getmaxdigit(b)+1;//最小进制为最大数位+1
long r=max(des,l);//最大进制为目的数本身
while(l<=r){
long mid=l+r>>1;
long t=f(b,mid);
if(t==-1||t>des){//若溢出,则当前进制太大
r=mid-1;
}
else l=mid+1;
}
if(f(b,l-1)==des) out.print(l-1);
else out.print("Impossible");
out.close();
}
1011.World Cup Betting
简单模拟,找到每组的最大值即可
public static void main(String[] args) throws Exception {
double a,b,c,max=0,ans=1;
char[] res=new char[3];
for(int i=0;i<3;i++){
a=in.readDouble();
b=in.readDouble();
c=in.readDouble();
max=max(max(a,b),c);
ans*=max;
if(max==a) res[i]='W';
else if(max==b) res[i]='T';
else res[i]='L';
}
ans=(ans*0.65-1)*2;
out.print(res[0]+" "+res[1]+" "+res[2]+" "+new DecimalFormat(".00").format(ans));
out.close();
}
1012.The Best Rank
排序,二分
找出每个人在四个科目中的最优名次,输出即可
static int binarySearch(Integer[] a,int x){
int n=a.length-1;
if(x==a[0]) return 0;
int l=0,r=n;
while(l<=r){
int mid=l+r>>1;
if(a[mid]<=x) r=mid-1;
else l=mid+1;
}
return l;
}
public static void main(String[] args) throws Exception {
n=in.readInt();
int q=in.readInt();
HashMap<String,int[]> map=new HashMap<>();
Integer[] C=new Integer[n];
Integer[] M=new Integer[n];
Integer[] E=new Integer[n];
Integer[] A=new Integer[n];
for(int i=0;i<n;i++){
String s=in.readString();
C[i]=in.readInt();
M[i]=in.readInt();
E[i]=in.readInt();
A[i]=(C[i]+M[i]+E[i])/3;
map.put(s,new int[]{C[i],M[i],E[i],A[i]});
}
Arrays.sort(C,(i,j)->(j-i));
Arrays.sort(M,(i,j)->(j-i));
Arrays.sort(E,(i,j)->(j-i));
Arrays.sort(A,(i,j)->(j-i));
int c,m,e,a;
while(q-->0){
String s=in.readString();
if(!map.containsKey(s)) out.printLine("N/A");
else{
int[] t=map.get(s);
c=t[0];m=t[1];e=t[2];a=t[3];
int idx1=binarySearch(C,c);
int idx2=binarySearch(M,m);
int idx3=binarySearch(E,e);
int idx4=binarySearch(A,a);
int ans=min(min(min(idx1,idx2),idx3),idx4);
ans++;
if(ans==idx4+1) out.printLine(ans+" A");
else if(ans==idx1+1) out.printLine(ans+" C");
else if(ans==idx2+1) out.printLine(ans+" M");
else out.printLine(ans+" E");
}
}
out.close();
}
1013.Battle Over Cities
给出一张无向图,求在给定删除某点后需要添加多少条边使整图连通。问题可转换为求出有多少连通块。
1.并查集
static class Edge{
int u,v;
public Edge(int u, int v) {
this.u = u;
this.v = v;
}
}
static Vector<Edge> e;
static int[] fa;
static void Init(int n){
e=new Vector<>();
fa=new int[n+1];
}
static int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
static void reFill(){
for(int i=1;i<=n;i++) fa[i]=i;
}
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
int k=in.readInt();
Init(n);
while(m-->0){
u=in.readInt();
v=in.readInt();
e.add(new Edge(u,v));
}
while(k-->0){
reFill();
HashSet<Integer> set=new HashSet<>();
int q=in.readInt();
for(Edge edge:e){
u=edge.u;
v=edge.v;
if(u==q||v==q) continue;
int fu=find(u);
int fv=find(v);
if(fv!=fu) fa[fu]=fv;
}
for(int i=1;i<=n;i++){
if(i==q) continue;
set.add(find(i));
}
out.printLine(set.size()-1);
}
out.close();
}
2.建图跑dfs
static class Graph{
int n,m,cnt=0;
Vector<Integer>[] h;
boolean[] vis;
public Graph(int n, int m) {
this.n = n;
this.m = m;
h=new Vector[n+1];
for(int i=0;i<=n;i++) h[i]=new Vector<>();
}
public void dfs(int v){
for(int i=1;i<=n;i++){
if(vis[i]||i==v) continue;
cnt++;
dfs(i,-1,v);
}
}
public void dfs(int x,int p,int re){
vis[x]=true;
for(int i=0;i<h[x].size();i++){
int v=h[x].get(i);
if(v==p||vis[v]||v==re) continue;
dfs(v,u,re);
}
}
public void reFill(){
cnt=0;
vis=new boolean[n+1];
}
}
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
int k=in.readInt();
Graph G=new Graph(n,m);
while(m-->0){
u=in.readInt();
v=in.readInt();
G.h[u].add(v);
G.h[v].add(u);
}
int ans=0;
while(k-->0){
v=in.readInt();
G.reFill();
G.dfs(v);
ans=G.cnt-1;
out.printLine(ans);
}
out.close();
}
1014.Waiting in Line
队列,模拟
n个窗口用n个队列来实现,每次遍历所有窗口,弹出时间最小的元素,并添加新元素到该队列。
注意若某客人的开始时间严格小于17:00,即使完成时间超过17:00,也算完成。
static int t = 1, n, m,u,v,w;
static int[] a;
static int[] pre;
static int[] ans;
static Queue<int[]>[] q;
static void Init(int n,int k){
a=new int[k+1];
pre=new int[k+1];
ans=new int[k+1];
q=new Queue[n+1];
for(int i=1;i<=n;i++) q[i]=new ArrayDeque<>();
}
static int[] f(){
int idx=0;
int t=Integer.MAX_VALUE;
for(int i=n;i>=1;i--){
if(!q[i].isEmpty()){
if(pre[i]+q[i].peek()[1]<=t){
t=pre[i]+q[i].peek()[1];
idx=i;
}
}
}
if(idx==0) return new int[]{0,0,0};//是否全为空,此时结束的最小下标窗口,此时的时间
pre[idx]+=q[idx].peek()[1];
return new int[]{1,idx,pre[idx]};
}
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
int k=in.readInt();
int Q=in.readInt();
int idx=0;
Init(n,k);
for(int i=1;i<=k;i++){
a[i]=in.readInt();
idx=i%n;
if(idx==0) idx=n;
if(q[idx].size()<m){
q[idx].add(new int[]{i,a[i]});
}
}
if(m*n<k) idx=m*n+1;
else idx=0;
while(true){
int[] res=f();
if(res[0]==0) break;
ans[q[res[1]].poll()[0]]=res[2];
if(idx==0) continue;
if(idx<=k) q[res[1]].add(new int[]{idx,a[idx++]});
}
DecimalFormat df=new DecimalFormat("00");
while(Q-->0){
int x=in.readInt();
int h=8+ans[x]/60;
m=ans[x]%60;
int startH=8+(ans[x]-a[x])/60;
int startE=(ans[x]-a[x])%60;
if(startH>=18) out.printLine("Sorry");
else {
String start=df.format(startH)+":"+df.format(startE);
String end = df.format(h) + ":" + df.format(m);
if(start.compareTo("16:59")<=0) out.printLine(end);
else out.printLine("Sorry");
}
}
out.close();
}
1015. Reversible Primes
素数筛,进制转换
素数筛法板子题,方法很多,此处给出欧拉筛法
static int t = 1, n, m,u,v,w,N=(int)1e5;
static boolean[] vis=new boolean[N+10];
static ArrayList<Integer> list=new ArrayList<>();
static void f(){
vis[0]=true;
vis[1]=true;
for(int i=2;i<=N;i++){
if(!vis[i]) list.add(i);
for (Integer integer : list) {
if (i * integer > N) break;
vis[i * integer] = true;
if (i % integer == 0) break;
}
}
}
static int slove(int n,int radix){
StringBuilder sb=new StringBuilder(Integer.toString(n,radix)).reverse();
return Integer.parseInt(sb.toString(),radix);
}
public static void main(String[] args) throws Exception {
f();
while(true){
n=in.readInt();
if(n<0) break;
int radix=in.readInt();
if(vis[n]) {
out.printLine("No");
continue;
}
int ans=slove(n,radix);
if(!vis[ans]) out.printLine("Yes");
else out.printLine("No");
}
out.close();
}
1019.General Palindromic Number
十进制转其他进制,并判断转换后是否是回文形式
static Vector<Integer> slove(int n,int radix){
Vector<Integer> ans=new Vector<>();
while(n!=0){
ans.add(n%radix);
n/=radix;
}
return ans;
}
public static void main(String[] args) throws Exception {
n=in.readInt();
int radix=in.readInt();
Vector<Integer> ans=slove(n,radix);
int f=0;
for(int i=0,j= ans.size()-1;i<=j;i++,j--){
if(!Objects.equals(ans.get(i), ans.get(j))){
f=1;
break;
}
}
if(f==0) out.printLine("Yes");
else out.printLine("No");
for(int i=ans.size()-1;i>=0;i--){
if(i!=ans.size()-1) out.print(" ");
out.print(ans.get(i));
}
out.close();
}
1021.Deepest Root(C++)
给定n点和n-1条边,判断此图是否是一个树。输出相应的连通块数量和有最长边的根节点
数据范围较小,两次dfs即可。
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <queue>
using namespace std;
const int N = 1e4 + 10;
int a[N],pre[N];
int n, u, v;
bool vis[N];
struct edge {
int u, v, w;
edge(int u, int v, int w) {
this->u = u;
this->v = v;
this->w = w;
}
};
vector<edge> e;
vector<int> h[N];
void dfs_block(int u,int p) {
if (vis[u]) return;
vis[u] = 1;
for (int ed : h[u]) {
int v = e.at(ed).v;
if (v == p) continue;
dfs_block(v, u);
}
}
int getBlockNumber() {
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
cnt++;
dfs_block(i, -1);
}
}
return cnt;
}
void add(int u, int v, int w) {
e.push_back(edge(u,v,w));
h[u].push_back(e.size()-1);
}
int dfs(int u, int p) {
int ans = 0;
for (int ed : h[u]) {
int v = e.at(ed).v;
if (v == p) continue;
ans = max(dfs(v, u) + 1, ans);
}
return ans;
}
vector<int> solve() {
vector<int> vec;
int max = 0;
for (int i = 1; i <= n; i++) {
int len = dfs(i, -1);
if (len > max) {
max = len;
vec.clear();
vec.push_back(i);
}
else if (len == max) vec.push_back(i);
}
return vec;
}
int main()
{
cin >> n;
for (int i = 0; i < n - 1; i++) {
cin >> u >> v;
add(u, v, 1);
add(v, u, 1);
}
int res = getBlockNumber();
if (res != 1)
cout << "Error: " << res << " components";
else {
vector<int> ans = solve();
sort(ans.begin(),ans.end());
for (int i : ans) {
cout << i << endl;
}
}
return 0;
}
1023.Have Fun with Numbers
判断一个数乘2后是否由原来的数位组成,数位较长,用大数
public static void main(String[] args) throws Exception {
String s=in.readStringLine();
BigInteger a=new BigInteger(s);
BigInteger ans=a.multiply(BigInteger.valueOf(2));
HashSet<Character> set1=new HashSet<>();
HashSet<Character> set2=new HashSet<>();
String res=String.valueOf(ans);
for(int i=0;i<s.length();i++) set1.add(s.charAt(i));
for(int i=0;i<res.length();i++) set2.add(res.charAt(i));
if(set1.equals(set2)) out.printLine("Yes");
else out.printLine("No");
out.printLine(res);
out.close();
}
1024.Palindromic Number
给定一个数和操作次数,求出该数加上自身反转后成为回文数的最小步数是否在给定次数内。
若是,输出此数和最小步数;否则输出最后操作结果
数据较长,用大数
static boolean check(BigInteger x){
String s=String.valueOf(x);
for(int i=0,j=s.length()-1;i<j;i++,j--){
if(s.charAt(i)!=s.charAt(j)) return false;
}
return true;
}
static BigInteger reverse(BigInteger a){
String s=String.valueOf(a);
StringBuilder sb=new StringBuilder(s);
return new BigInteger(sb.reverse().toString());
}
public static void main(String[] args) throws Exception {
long a=in.readLong();
int k=in.readInt();
int cnt=0;
BigInteger b=BigInteger.valueOf(a);
while(cnt<k){
if(check(b)){
break;
}
cnt++;
b=b.add(reverse(b));
}
out.printLine(b);
out.printLine(cnt);
out.close();
}
1027. Colors in Mars
给定三个数,输出他们各自13进制下的形式
static String Calc(int a,HashMap<Integer,String> map){
StringBuilder sb=new StringBuilder("");
while(a!=0){
int mod=a%13;
sb.append(mod<=9?String.valueOf(mod):map.get(mod));
a/=13;
}
if(sb.length()==1) sb.append("0");
else if(sb.length()==0) sb.append("00");
return sb.reverse().toString();
}
public static void main(String[] args) throws Exception {
int a,b,c;
a=in.readInt();
b=in.readInt();
c=in.readInt();
HashMap<Integer,String> map=new HashMap<>(){{
put(10,"A");
put(11,"B");
put(12,"C");
}};
String ans="#"+Calc(a,map)+Calc(b,map)+Calc(c,map);
out.print(ans);
out.close();
}
1028.List Sorting(C++)
自定义字符串排序
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
struct Student
{
string id;
string name;
int score;
};
bool cmp1(Student stu1, Student stu2)
{
return stu1.id < stu2.id;
}
bool cmp2(Student stu1, Student stu2)
{
return stu1.name == stu2.name ? stu1.id < stu2.id : stu1.name < stu2.name;
}
bool cmp3(Student stu1, Student stu2)
{
return stu1.score == stu2.score ? stu1.id < stu2.id : stu1.score < stu2.score;
}
vector<Student> arr;
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
Student stu;
cin >> stu.id >> stu.name >> stu.score;
arr.push_back(stu);
}
if (m == 1)
{
sort(arr.begin(), arr.end(), cmp1);
for (int i = 0; i < n; i++)
{
cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
}
}
if (m == 2)
{
sort(arr.begin(), arr.end(), cmp2);
for (int i = 0; i < n; i++)
{
cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
}
}
if (m == 3)
{
sort(arr.begin(), arr.end(), cmp3);
for (int i = 0; i < n; i++)
{
cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
}
}
}
1029.Median(C++)
找出给定的两个升序序列的中位数。从前往后,不断遍历即可。
#include<iostream>
#include<cstring>
using namespace std;
int main() {
int n=0, m=0;
cin >> n;
int a[n + 1];
for (int i = 1; i <= n; i++) cin >> a[i];
cin >> m;
int b[m + 1];
for (int i = 1; i <= m; i++) cin >> b[i];
int mid = n + m + 1 >> 1;
int p = 0, i = 1, j = 1, k = 0;
while (k != mid) {
if (i == n + 1) {
p = b[j]; j++; k++; continue;
}
if (j == m + 1) {
p = a[i]; i++; k++; continue;
}
if (a[i] <= b[j]) {
p = a[i];
i++;
}
else {
p = b[j];
j++;
}
k++;
}
cout << p;
}
1030.Travel Plan
Dijkstra最短路加路径输出
public static void main(String[] args) throws Exception {
n=in.readInt();
m=in.readInt();
int s=in.readInt();
int end=in.readInt();
Graph g=new Graph(n,m);
int d;
for(int i=0;i<m;i++){
u=in.readInt();
v=in.readInt();
d=in.readInt();
w=in.readInt();
g.add(u,v,d,w);
g.add(v,u,d,w);
}
Graph.Result result=g.Dijkstra(s,end,true);
out.printCollection(result.path);
out.print(" "+result.d+" "+result.w);
out.close();
}
class Graph
{
int n,m,INF=0x3f3f3f3f,blockNumber=0,u,v;
Vector<edge> e=new Vector<>();
Vector<Integer>[] h;
public Graph(int n, int m) {
this.n = n;
this.m = m;
h=new Vector[n+1];
for(int i=0;i<=n;i++) h[i]=new Vector<>();
}
class edge{
int u,v,w,d;
public edge(int u, int v, int d) {
this.u = u;
this.v = v;
this.w = d;
}
public edge(int u, int v, int d, int w) {
this.u = u;
this.v = v;
this.w = w;
this.d = d;
}
}
void add(int u,int v,int w){
e.add(new edge(u,v,w));
h[u].add(e.size()-1);
fa[v]=u;
}
void add(int u,int v,int w,int d){
e.add(new edge(u,v,w,d));
h[u].add(e.size()-1);
fa[v]=u;
}
class Result{
int d,w;
Deque<Integer> path=new ArrayDeque<>();
public Result(int d) {
this.d = d;
}
public Result(int d, Deque<Integer> path) {
this.d = d;
this.path = path;
}
}
Result Dijkstra(int begin,int end,boolean f){
Result result;
int[] dis=new int[n+1];
int[] p=new int[n+1];
boolean[] vis=new boolean[n+1];
int[] val=new int[n+1];
Arrays.fill(val,INF);
Arrays.fill(dis,INF);
Arrays.fill(p,-1);
PriorityQueue<int[]> q=new PriorityQueue<>((a,b)->(a[0]-b[0]));
q.offer(new int[]{0,begin});
dis[begin]=0;
val[begin]=0;
while(!q.isEmpty()){
int[] t=q.poll();
int u=t[1];
if(vis[u]) continue;
vis[u]=true;
for(int ed:h[u]){
int v=e.get(ed).v;
int d=e.get(ed).d;
int w=e.get(ed).w;
if(dis[u]+d<dis[v]){
dis[v]=dis[u]+d;
val[v]=val[u]+w;
q.offer(new int[]{dis[v],v});
p[v]=u;
}
else if(dis[u]+d==dis[v]){
if(val[u]+w<val[v]) p[v]=u;
val[v]=min(val[u]+w,val[v]);
q.offer(new int[]{dis[v],v});
}
}
}
if(f){
int cur=end;
Deque<Integer> path=new ArrayDeque<>();
while(cur!=-1) {
path.push(cur);
cur = p[cur];
}
result=new Result(dis[end],path);
}
else result=new Result(dis[end]);
result.w=val[end];
return result;
}
}
1031.Hello World for U
给定字符串输出其最方正的“U”字形式。
public static void main(String[] args) throws Exception {
String s=in.readStringLine();
n=s.length();
if((n-2)%3==0){
c=(n-2)/3;
}
else if((n-2)%3==1){
c=(n-2)/3+1;
}
else c=(n-2)/3;
int i=0,j=s.length()-1;
for(int k=0;k<(n-c)/2-1;k++){
for(int q=0;q<c+2;q++){
if(q==0) out.print(s.charAt(i++));
else if(q==c+1) out.printLine(s.charAt(j--));
else out.print(' ');
}
}
for(int k=i;k<=j;k++) out.print(s.charAt(k));
out.close();
}
1038.Recover the Smallest Number(C++)
给定n个数,输出这n个数能顺序组成的最小数。
自定义排序,满足任意两数的字符串形式相加小于后两数即可。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e4 + 10;
string str[N];
bool cmp(string a, string b) {
return a + b < b + a;
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> str[i];
sort(str, str + n, cmp);
string ans = "";
for (int i = 0; i < n; i++) ans += str[i];
int i = 0;
while (i < ans.size() && ans[i] == '0') i++;
if (i == ans.size()) {
ans = "0";
}
else {
ans = ans.substr(i);
}
cout << ans;
return 0;
}
1040.Longest Symmetric String
求出给定字符串的最长回文子串,马拉车经典算法
import java.util.Scanner;
public class Main {
static Scanner in=new Scanner(System.in);
public static int maxPalindrome(String s){
int curCenter=0,curRight=0,maxLen=0;
int n=s.length()*2+2;
char[] sb=new char[n];
int[] p=new int[n];
sb[0]='$';
sb[1]='#';
int j=2;
for(int i=0;i<s.length();i++){
sb[j++]=s.charAt(i);
sb[j++]='#';
}
for(int i=1;i<n;i++){
p[i]=curRight>i?Math.min(p[2*curCenter-i],curRight-i):1;
while(i-p[i]>=0&&i+p[i]<n&&sb[i-p[i]]==sb[i+p[i]]) p[i]++;
if(curRight<i+p[i]){
curRight=i+p[i];
curCenter=i;
}
if(maxLen<p[i]){
maxLen=p[i];
}
}
return maxLen-1;
}
public static void main(String[] args) {
String s=in.nextLine();
int n=maxPalindrome(s);
System.out.print(n);
}
}
1041.Be Unique
找出第一个出现的不重复数字
public static void main(String[] args) throws Exception {
int n=in.readInt();
int[] a=new int[n+1];
int[] cnt=new int[N];
for(int i=1;i<=n;i++){
a[i]=in.readInt();
cnt[a[i]]++;
}
boolean f=false;
int ans=0;
for(int i=1;i<=n;i++){
if(cnt[a[i]]==1){
f=true;
ans=a[i];
break;
}
}
if(f) out.print(ans);
else out.print("None");
out.close();
}
1042.Shuffling Machine
模拟,找出每个字符串n次变换后的位置
public static void main(String[] args) throws Exception {
String[] a=new String[55];
int i=1;
for(i=1;i<=13;i++){
a[i]=String.valueOf("S"+i);
}
for(i=14;i<=26;i++){
a[i]=String.valueOf("H"+(i-13));
}
for(i=27;i<=39;i++){
a[i]=String.valueOf("C"+(i-26));
}
for(i=40;i<=52;i++){
a[i]=String.valueOf("D"+(i-39));
}
a[53]="J1";
a[54]="J2";
n=in.readInt();
int[] cnt=new int[55];
for(i=1;i<=54;i++){
cnt[i]=in.readInt();
}
String[] b=a.clone();
int idx=0,j=1;
for(i=1;i<=54;i++){
j=1;
m=cnt[i];
while(j<=n){
idx=m;
m=cnt[idx];
j++;
}
b[idx]=a[i];
}
out.printArrayBySpace(b,1,55);
out.close();
}
1044.Shopping in Mars(C++)
找出n个数中区间和刚好等于给定值的左右端点。若不存在,则输出区间和大于给定值的最接近的区间的端点。
双指针经典题型,不过比较的过程需要用到优先队列。注意输出格式
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int a[N],pre[N];
struct node {
int l, r, res;
node(int l,int r,int res) {
this->l = l;
this->r = r;
this->res = res;
}
node(const node& other) {
this->l = other.l;
this->r = other.r;
this->res = other.res;
}
bool operator<(const node& other) const {
return res == other.res? l>other.l : res>other.res;
}
};
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
int l = 1, r = 1,sum=0;
priority_queue<node,vector<node>> q;
while (r <= n) {
sum += a[r];
if (sum == m) {
q.push(node{l, r, 0});
}
while (sum > m && l <= n) {
q.push(node{l, r, pre[r] - pre[l - 1]});
sum -= a[l++];
if (sum == m) {
q.push(node{l, r, 0});
}
}
r++;
}
int minCost = q.top().res,i=1;
while (!q.empty()) {
node p = q.top();
q.pop();
if (p.res == minCost) {
if (i == 1) cout << p.l << "-" << p.r;
else cout << endl << p.l <<"-"<< p.r;
}
else break;
i++;
}
return 0;
}
1045.Favorite Color Stripe
给出长度为n和m的两个数组a和b,求出按照a中元素顺序出现的顺序序列在b中的最长长度。即求最长不降子序列长度。
本质是最长上升子序列的变形题。注意没有出现的数字以及最后不要打印换行。
Java暴力写法会超时;加上快读快写可以AC
二分优化不加快读快写即可AC,感觉出题人在卡暴力做法。
import java.util.Arrays;
import java.util.Scanner;
public class Main {
//新元素要替换掉第一个>(=)其本身的元素
//若没有,将其添加到末尾
//注意c中并不是真正的上升子序列
static Scanner in=new Scanner(System.in);
static int find(int x,int len,int[] c){
int l=1,r=len,mid;
while(l<=r){
mid=l+r>>1;
if(x>=c[mid]) l=mid+1;
else r=mid-1;
}
return l;
}
public static void main(String[] args) {
int N=in.nextInt();
int n=in.nextInt();
int[] idx=new int[N+1];
for(int i=1;i<=n;i++){
int a=in.nextInt();
idx[a]=i;
}
int m=in.nextInt();
int[] b=new int[m+1];
for(int i=1;i<=m;i++) {
int x=in.nextInt();
if(idx[x]!=0) b[i]=idx[x];
}
int len=0;
int[] c=new int[m+1];
for(int i=1;i<=m;i++){
if(b[i]==0) continue;
if(len==0){
c[++len]=b[i];
continue;
}
if(b[i]>=c[len]) c[++len]=b[i];
else{
int j=find(b[i],len,c);
c[j]=b[i];
}
}
System.out.print(len);
}
}