目录
特别的玛格丽特
题目描述
给定一个数组。每次可以交换数组中两个奇数或者两个偶数,可以交换无数次。问最后是否能把数组变成非降序数组?
用数学语言来说,对于数组aa,每次可以交换 a_iai 和 a_jaj ,当且仅当i≠ji=j 且 (a_i-a_j)\ mod\ 2=0(ai−aj) mod 2=0。问经过一些操作后,最终是否能使得数组满足:对于 i∈[1,n)i∈[1,n),a_i\leq a_{i+1}ai≤ai+1?
输入描述:
第一行输入一个正整数 nn ,代表数组的长度。 第二行输入 nn 个正整数 a_iai ,代表拿到的数组。 1\leq n ,a_i \leq 1001≤n,ai≤100
输出描述:
如果最终能使数组变成非降序,则输出"Yes"。否则输出"No"。
示例1
输入
复制
5 3 2 1 4 5
输出
复制
Yes
示例2
输入
复制
5 1 3 2 2 5
输出
复制
No
思路:将奇数和偶数分开保存,用集合分别记录其下标,对奇数数组和偶数数组进行排序,然后根据各自包含的索引,将a数组进行更新,在判断a数组是否是非降序。
import java.util.Arrays;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
int a[]=new int[n];
int b[]=new int[n];//存储偶数;
Set<Integer>set=new TreeSet<>();//存储偶数下标;
int c[]=new int[n];//存储奇数;
Set<Integer>set1=new TreeSet<>();//存储奇数下标;
int k=0,k1=0;
for(int i=0;i<n;i++) {
a[i]=cin.nextInt();
if(a[i]%2==0) {
b[k++]=a[i];
set.add(i);
}else {
c[k1++]=a[i];
set1.add(i);
}
}
Arrays.sort(b,0,k);
Arrays.sort(c,0,k1);
int h=0,h1=0,h2=0;
for(int i=0;i<n;i++) {
if(set.contains(i)) {
a[h++]=b[h1++];
}else {
a[h++]=c[h2++];
}
// System.out.println(a[h-1]);
}
int flag=0;
for(int i=1;i<n;i++) {
if(a[i]<a[i-1]) {
flag=1;break;
}
}
if(flag==0)System.out.println("Yes");
else System.out.println("No");
}
}
野比大雄的作业
题目描述
大雄喜欢二进制。
大雄面前有一个 nnn 个数的序列 aaa,对于一个区间 [l,r][l,r][l,r],设
ans=(al and al+1 and……and ar−1 and ar)+(al or al+1 or……or ar−1 or ar)ans=(a_l\ \text{and}\ a_{l+1}\ \text{and}……\text{and}\ a_{r-1}\ \text{and}\ a_r ) +(a_l\ \text{or}\ a_{l+1}\ \text{or}……\text{or}\ a_{r-1}\ \text{or}\ a_r)ans=(al and al+1 and……and ar−1 and ar)+(al or al+1 or……or ar−1 or ar)
输出最大的 ansansans 值。
输入描述:
第一行一个正整数 n (1≤n≤105)n\ (1\leq n\leq 10^5)n (1≤n≤105)。 接下来一行 nnn 个非负整数 aia_iai (0≤ai≤109)\ (0\leq a_i\leq 10^9) (0≤ai≤109)。
输出描述:
一个数表示答案。
示例1
输入
复制5 4 8 2 3 1
5 4 8 2 3 1
输出
复制16
16
思路:经过推算可以发现最大值是最大数组的二倍。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
int max=0;
for(int i=0;i<n;i++) {
int a=cin.nextInt();
max=Math.max(max, a<<1);
}
System.out.println(max);
}
}
哦~唔西迪西小姐~
题目描述
唔西迪西现在正处在一个冰火迷宫中,迷宫由 nnn 个格子组成,每个格子要么是冰之格,要么是火之格,唔西迪西刚开始可以选择从迷宫中任意一个开始走,走到第 iii 个位置时会得到值为 aia_iai 的积分。(注意:唔西迪西也可以选择一个格子都不走)
如果唔西迪西当前在冰之格,那么她可以选择一个编号大于当前格子的冰之格,跳到那里。如果唔西迪西当前在火之格,那么她可以选择一个编号大于当前格子的火之格,跳到那里。如果唔西迪西目前没有格子可以走,那么结束。同时,即使存在可以跳过去的格子,唔西迪西也可以选择在任意时刻结束。
唔西迪西想最大化她的得分,于是她学会了一个超能力,她能在比赛开始的时候改变最多 mmm 个格子的状态,即将一个格子从冰之格变成火之格或从火之格变成冰之格,改变第 iii 个格子的状态会让唔西迪西的得分减少 pip_ipi 。(唔西迪西改变格子的状态后才开始挑选起点开始行动,也就是说,得分分成两部分,一部分是改变格子状态的得分,一部分是走格子的得分)
你能告诉唔西迪西她最多得几分吗
输入描述:
第一行两个正整数 n,mn,mn,m (1≤n,m≤105)\ (1\leq n,m\leq 10^5) (1≤n,m≤105)。
第二行 nnn 个整数表示 aia_iai。
第三行 nnn 个整数表示 pip_ipi (−105≤ai,pi≤105)\ (-10^5\leq a_i,p_i \leq 10^5) (−105≤ai,pi≤105)。
第四行 nnn 个整数 bib_ibi 为 000 或 111,000 表示这个格子是冰之格,111 表示这个格子是火之格。
输出描述:
一个数表示答案。
示例1
输入
复制
3 2 1 15 9 2 5 7 1 0 1
输出
复制
20
示例2
输入
复制
10 3 80 86 57 69 59 52 94 74 9 63 8 32 77 64 53 49 22 68 27 63 1 0 0 0 1 0 0 1 1 1
输出
复制
442
思路:此题有好几个坑点,被坑傻了T-T
首先,分析题,我们可以从火之格或者冰之格任意出发,记录两种起始点开始的最大值即可。对于m个如何变,我们可以用一个大根堆记录所有变的所获得的最大值,然后选前m个加入即可。
因为题意说,变化时需要-p[i],如果走就+a[i],但是考虑到a[i]和p[i]都有正负值,所以,当将一个格子变为可以走的格子时,优先队列需要放入max(-p[i],-p[i]+a[i]),当将一个格子变为不可以走的格子时,优先队列需要放入-p[i]+max(a[i],0);一直保证最优。
import java.util.*;
import java.io.*;
public class Main {
static class FastScanner{
BufferedReader br;
StringTokenizer st;
public FastScanner(InputStream in) {
br=new BufferedReader(new InputStreamReader(in),16834);
eat("");
}
public void eat(String s) {
st=new StringTokenizer(s);
}
public String nextLine() {
try {
return br.readLine();
}catch(IOException e) {
return null;
}
}
public boolean hasNext() {
while(!st.hasMoreTokens()) {
String s=nextLine();
if(s==null)return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
}
static FastScanner cin=new FastScanner(System.in);
static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) {
int n=cin.nextInt(),m=cin.nextInt();
int a[]=new int[n];
int p[]=new int[n];
int b[]=new int[n];
PriorityQueue<Long>q=new PriorityQueue<>(new Comparator<Long>() {
@Override
public int compare(Long o1, Long o2) {
// TODO Auto-generated method stub
if(o1<o2)return 1;
return -1;
}
});
for(int i=0;i<n;i++)a[i]=cin.nextInt();
for(int i=0;i<n;i++)p[i]=cin.nextInt();
for(int i=0;i<n;i++) {
b[i]=cin.nextInt();
}
long sum=0,ans=0;
for(int i=0;i<n;i++) {
if(b[i]==0) {
sum+=Math.max(0,a[i]);
q.add((long) (-p[i]-Math.max(0, a[i])));
}
else {
q.add((long) (Math.max(-p[i]+a[i],-p[i])));
}
}
for(int i=0;i<m&&q.size()>0;i++) {
long t=q.poll();
if(t<0)break;
sum+=t;
}
ans=Math.max(ans,sum);
sum=0;q.clear();
for(int i=0;i<n;i++) {
if(b[i]==1) {
sum+=Math.max(0,a[i]);
q.add((long) (-p[i]-Math.max(0, a[i])));
}
else {
q.add((long) (Math.max(-p[i]+a[i],-p[i])));
}
}
for(int i=0;i<m&&q.size()>0;i++) {
long t=q.poll();
if(t<0)break;
sum+=t;
}
out.println(Math.max(ans,sum));
out.flush();
}
}
月之暗面
题目描述
I'll see you on the dark side of the moon.
我们将在月之暗面相会。
给出一棵 nnn 个点的树,有 xxx 种普通颜色,yyy 种特殊颜色
现在要给树上的每个节点染色,普通颜色染色没有限制,但两个相邻的节点不能染相同颜色的特殊颜色
求染色方案数,答案对 998244353998244353998244353 取模。
输入描述:
第一行三个整数 n,x,yn,x,yn,x,y ( 1≤n≤106,1≤x,y≤1091\leq n \leq 10^6,1\leq x,y\leq 10^91≤n≤106,1≤x,y≤109 ) ,分别表示树的节点数,普通颜色的种数,特殊颜色的种数
接下来 n−1n-1n−1 行描述这棵树,每行两个整数 u,vu,vu,v ( 1≤u,v,≤n1\leq u,v,\leq n1≤u,v,≤n ) 表示从 uuu 到 vvv 有一条树边
保证输入的树合法。
输出描述:
一行一个整数,表示答案。
示例1
输入
复制2 1 2 1 2
2 1 2 1 2
输出
复制7
7
示例2
输入
复制5 3 3 1 2 1 3 3 4 3 5
5 3 3 1 2 1 3 3 4 3 5
输出
复制5664
5664
示例3
输入
复制11 45 14 6 5 6 7 7 9 7 8 9 2 8 10 2 1 8 3 10 4 4 11
11 45 14 6 5 6 7 7 9 7 8 9 2 8 10 2 1 8 3 10 4 4 11
输出
复制188688550
188688550
思路:通过树状dp求解,f[i][0]表示使用普通颜色,f[i][1]表示使用特殊颜色。以1为起始点开始搜,然后记录,为了防止往回搜,dfs时记录上一个节点,即父节点,如果和上一个节点是特殊颜色,那么这个节点只能使用x个普通颜色加(y-1)种特殊颜色,否则这个节点能使用x个普通颜色加y种特殊颜色。累乘即可。
import java.util.*;
import java.io.*;
public class Main {
static class FastScanner{
BufferedReader br;
StringTokenizer st;
public FastScanner(InputStream in) {
br=new BufferedReader(new InputStreamReader(in),16834);
eat("");
}
public void eat(String s) {
st=new StringTokenizer(s);
}
public String nextLine() {
try {
return br.readLine();
}catch(IOException e) {
return null;
}
}
public boolean hasNext() {
while(!st.hasMoreTokens()) {
String s=nextLine();
if(s==null)return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
}
static FastScanner cin=new FastScanner(System.in);
static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N=1000010,mod= 998244353;
static long f[][]=new long[N][2];
static Vector<Integer> a[]=new Vector[N];
static int x,y,n;
public static void main(String[] args) {
n=cin.nextInt();
x=cin.nextInt();
y=cin.nextInt();
for(int i=0;i<N;i++)
a[i]=new Vector<>();
for(int i=0;i<n-1;i++) {
int u=cin.nextInt();
int v=cin.nextInt();
a[u].add(v);a[v].add(u);
}
dfs(1,0);
// out.println(f[1][0]+" "+f[1][1]);
out.println((f[1][0]+f[1][1]*y)%mod);
out.flush();
}
private static void dfs(int sb, int fa) {
// TODO Auto-generated method stub
f[sb][0]=x;f[sb][1]=1;
for(int i=0;i<a[sb].size();i++) {
int t=a[sb].get(i);
if(t==fa)continue;
dfs(t,sb);
f[sb][0]=f[sb][0]*(f[t][0]+y*f[t][1]%mod)%mod;
f[sb][1]=f[sb][1]*(f[t][0]+(y-1)*f[t][1]%mod)%mod;
}
}
}