题目链接
知识一览
01-贪心
02-线性筛
03-堆优化Dijkstra
题目列表
快输
static class FastReader{
BufferedReader br;
StringTokenizer st;
String tmp;
public FastReader() {
br=new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while(st==null||!st.hasMoreElements()) {
try {
st=new StringTokenizer(br.readLine());
}catch(IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong(){return Long.parseLong(next());}
String nextLine() {
String str="";
try {
str=br.readLine();
}catch(IOException e) {
e.printStackTrace();
}
return str;
}
boolean hasNext(){
if(st!=null&&st.hasMoreTokens())return true;
try {
tmp=br.readLine();
st=new StringTokenizer(tmp);
}catch(IOException e) {
return false;
}
return true;
}
}
static PrintWriter out=new PrintWriter(
new BufferedWriter(new OutputStreamWriter(System.out)));
static FastReader sc=new FastReader();
C 阿宁吃粽子(排序/贪心)
题目描述
阿宁的公司给阿宁发了各种口味的粽子。
一共有 n条粽子,每条粽子有个美味值 ai。
阿宁想立即吃下全部。吃下第 k条粽子时,该粽子的美味值是 x,阿宁获得 2^(k mod 10) ×x 的愉悦值。(k 从 1开始)
阿宁想安排一下吃粽子的顺序,使她获得的愉悦值最大。
输入描述:
第一行输入一个正整数 n。
第二行输入 n 个正整数 ai,ai表示第 i条粽子的美味值。
1≤n,ai ≤2×10^5
输出描述:
一行输出 n 个正整数,第 j 个数表示吃下的第 j 条粽子的美味值。
如果有多解,请把美味值较大的粽子,安排到后面。(好吃的留到后面)
示例1
输入
3
3 1 2
输出
1 2 3
说明
该方案美味值为 1 * 2^1 + 2 * 2^2 + 3 * 2^3 = 34,没有别的方案的愉悦值大于 34。
示例2
输入
12
4 4 4 3 3 3 2 2 2 1 1 1
输出
1 2 2 3 3 3 4 4 4 1 1 2
public static void main(String[] args) {
int n=sc.nextInt();
int[] a=new int[n];
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
}
int b[]=new int[]{9,0,1,2,3,4,5,6,7,8};
Arrays.sort(a);
int[] ans=new int[n];
int cnt=-1;
for(int i=0;i<10;i++){
for(int j=b[i];j<n;j+=10){
ans[j]=a[++cnt];
}
}
for(int i=0;i<n;i++)
out.print(ans[i]+" ");
out.flush();
}
D 阿宁的质数(线性筛)
题目描述
阿宁有一个长度为 n 的正整数数组 a,她有很多次询问,每次询问:在数组 a 的前 x 个数中,未出现的最小质数是多少?
输入描述:
第一行输入两个正整数 n,q,表示数组的长度和询问的次数。
第二行输入 n 个正整数 ai,表示数组的每一个元素i。
接下来 q 行,每行一个正整数 x,代表一次询问。
1≤n,q≤2×10^5
1≤ai≤10^9
1≤x≤n
输出描述:
输出 q 行,表示每次询问的答案。
示例1
输入
5 5
8 2 3 6 5
1
2
3
4
5
输出
2
3
5
5
7
说明
8 不是质数,未出现的最小质数是 2。
在 8,2 中,质数有 2,未出现的最小质数是 3。
在 8,2,3 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6,5 中,质数有 2,3,5,未出现的最小质数是 7。
法一
static int N=(int)1e7;
static int a[]=new int[10000001];
static boolean b[]=new boolean[10000001];
public static void main(String[] args) {
int n=sc.nextInt(),q=sc.nextInt();
for(int i=2;i<=N;i++){
if(!b[i]){
for(int j=i*2;j<=N;j+=i)
b[j]=true;
}
}
int tmp=2;
for(int i=1;i<=n;i++){
int x=sc.nextInt();
if(x<=N)b[x]=true;
while(b[tmp])tmp++;
a[i]=tmp;
}
while(q-->0){
out.println(a[sc.nextInt()]);
}
out.flush();
}
法二 线性筛
static int cnt=0;
static Set<Integer> st=new HashSet<>();
static int res[];
//N 的大小 3e6,大约有2e5多一点的质数
public static void main(String[] args) {
int n=sc.nextInt(),q=sc.nextInt();
res=new int[n+1];
f((int)3e6);
cnt=1;
for(int i=1;i<=n;i++){
st.add(sc.nextInt());
while(st.contains(prime[cnt]))cnt++;
res[i]=cnt;
}
while(q-->0){
out.println(prime[res[sc.nextInt()]]);
}
out.flush();
}
static int prime[]=new int[(int)3e5];
static boolean pd[]=new boolean[(int)4e6];
static void f(int n){//预处理2e5个质数
Arrays.fill(pd,true);
pd[1]=false;
for(int i=2;i<=n;i++){
if(pd[i])prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
pd[i*prime[j]]=false;
if(i%prime[j]==0)break;
}
}
}
E 阿宁睡大觉(贪心)
题目描述
阿宁经常在周末睡大觉。阿宁在膜法书上了解到,她睡觉时会产生字符串 ss,计算出她的睡觉质量为
其中定义 w(z)=0,w(Z)=2 。(前者小写后者大写)
为了睡一个好大觉,阿宁使用了预测膜法知道 s 串,然后她可以最多使用 k 次del膜法。使用一次del膜法可以删除 s 串的一个字符。
阿宁想知道睡觉质量的最大值是多少?
输入描述:
第一行输入两个正整数 n、k,表示字符串的长度和del膜法的最多使用次数。
第二行输入一个字符串 s,仅包含字符 ‘z’ 和 ‘Z’。
2≤n≤2×10^5
1≤k≤2×10^5
输出描述:
一个整数,睡觉质量的最大值。
示例1
输入
3 2
ZzZ
输出
4
说明
使用一次del膜法删除中间的 ‘z’,字符串为 “ZZ”,睡眠质量为 4。
示例2
输入
3 2
zzz
输出
0
static int n,k;
public static void main(String[] args) {
int n=sc.nextInt(),k=sc.nextInt();
char c[]=(sc.next()).toCharArray();
int l=0;
PriorityQueue<Integer> pq=new PriorityQueue<>();
boolean f=false;
for(int i=0;i<n;i++){
if(c[i]=='Z'){
if(f){
pq.add(l);
l=0;
}else f=true;
}else{
if(f)l++;
}
}
int ans=0;
while(k>0&&!pq.isEmpty()){
int t=pq.poll();
if(k<t)break;
k-=t;
ans+=4;
}
out.println(ans);
out.flush();
}
F 阿宁去游玩(图论/最短路/堆优化Dijkstra(邻接表))
题目描述
阿宁打算下次放假去游玩。一共有 n 个城市, 阿宁住在 1 号城市,去到 n 号城市游玩。
城市有两种属性,一种是炎热,另一种是酷寒,每个城市是其中一种。从一个城市前往另一个城市,如果要前往的城市和当前城市的属性相同,则需要 x 时间,否则需要 y 时间。
阿宁可以使用倒转膜法,该膜法可以使所有城市(除了阿宁当前所在的城市)的属性变化(炎热变酷寒,酷寒变炎热),花费 z 时间。倒转膜法可以使用任意次。
阿宁想尽快去到 n 号城市游玩,她想知道她最少需要多少时间到达目的地?
输入描述:
第一行输入两个正整数 n,m,表示一共有 n 个城市,m 条道路。
第二行输入三个正整数 x,y,z,表示不同动作花费的时间。
第三行输入 n 个正整数 ai,表示第 i 城市的属性,0 表示炎热,1 表示酷寒。
接下来 m 行,每行输入两个正整数 u,v,表示 u 号城市和 v 号城市有道路相连。
(道路是双向的,即 u 能走到 v,v 能走到 u)
保证 1 号城市能到达 n 号城市。
2≤n≤2×10^5
1≤m,x,y,z≤2×10^5
1≤u,v≤n
0≤ai≤1
输出描述:
一个整数,表示阿宁从 1 号城市到达 n 号城市所需要的最少时间。
示例1
输入
5 6
1 3 9
1 0 0 1 1
1 2
1 3
2 3
2 4
3 4
4 5
输出
7
说明
路径 1->3->4->5,花费时间为 3+3+1=7。
示例2
输入
3 3
1 10 2
0 1 1
1 2
1 3
2 3
输出
3
说明
在 11 号城市使用一次倒转膜法,路径 1->3,花费时间为 2+1=3。
static int N=(int)2e5+5,M=N<<1;
static long inf=(long)1e18;
static int[] h=new int[N],e=new int[M],ne=new int[M];//邻接表
static int idx=0;
static long[] a=new long[N];
static long[] dist=new long[N];
static void add(int a,int b) {
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
public static void main(String[] args) throws IOException {
int n=sc.nextInt(),m=sc.nextInt();
long x=sc.nextInt(),y=sc.nextInt(),z=sc.nextInt();
Arrays.fill(h,-1);
Arrays.fill(dist,inf);
for (int i=1;i<=n;i++) a[i]=sc.nextInt();
for (int i=1;i<=m;i++) {
int a=sc.nextInt(),b=sc.nextInt();
add(a,b);
add(b,a);
}
PriorityQueue<long[]> q = new PriorityQueue<>((o1, o2) -> Long.compare(o1[1], o2[1]));//lambda表达式
q.add(new long[]{1, 0});
while (!q.isEmpty()) {
long[] c=q.poll();
int u=(int)c[0];
long d=c[1];
for (int i=h[u];i!=-1;i=ne[i]) {//遍历所有出边
int son=e[i];
long w=0;
if (a[u]!=a[son]) w=Math.min(x+z,y);
else w=Math.min(y+z,x);
w+=d;
if (dist[son]>w) {
dist[son]=w;
q.add(new long[]{son,w});
}
}
}
out.println(dist[n]);
out.flush();
}