牛客练习赛97

目录

特别的玛格丽特

野比大雄的作业

哦~唔西迪西小姐~

月之暗面


特别的玛格丽特

题目描述 

给定一个数组。每次可以交换数组中两个奇数或者两个偶数,可以交换无数次。问最后是否能把数组变成非降序数组?

用数学语言来说,对于数组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;
			
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值