牛客小白月赛87

文章介绍了使用Java编程解决两个问题:数组构造中优化元素调整的方法,以及利用BIT数据结构(树状数组)计算逆序对的容斥法解题思路。

E.小苯的数组构造

解题思路
  • 调整x>y,此次代价为x-y
  • 不将x,y调整为z=x-t=y+t,而是直接将x调整y,代价一样,对于全局来说,代价也一样

import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;





public class Main{
	static long md=(long)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	
	
	static
	class Node{
		long x;
		int j;
		public Node(long X,int J) {
			x=X;
			j=J;
		}
	}
	
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
//	    int T=input.nextInt();
//	    while(T>0) {
//	    	
//	    	T--;
//	    }
	    
	    int n=input.nextInt();
	    long[] a=new long[n+1];
	    for(int i=1;i<=n;++i)a[i]=input.nextLong();
	    
	    //因为极差为高低值的差,不用将一高一低,一减一加变为平衡值
	    //直接将低值变为高值
	    long[] b=new long[n+1];
	    for(int i=1;i<n;++i) {
	    	if(a[i]>a[i+1]) {
	    		b[i+1]=a[i]-a[i+1];
	    		a[i+1]=a[i];
	    	}
	    }
	    for(int i=1;i<=n;++i) {
	    	out.print(b[i]+" ");
	    }
        
 	    out.flush();
	    out.close();
	}
	//System.out.println();
	//out.println();
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

 G.小苯的逆序对

    解题思路
  • 利用DP+容斥,可以求解出gcd(i,j)=1的对数
  • 已知f[d]gcd(i,j)=d的对数
  • f[d]=C^{2}_{m}-\sum_{k=2}^{n/d}f[kd] ,m=Num(x\%d==0)
  • for \ n \to 1,得出f[1]
  • 在求解的过程中加上逆序对的限制,则为答案
  • C^{2}_m\Rightarrow Num(i<j\&\&(i,j\%d==0))
  • d的倍数按顺序放入树状数组,对于当前值j,树状数组查询到当前大于j的个数
  • 全加起来即为Num(i<j\&\&(i,j\%d==0))
  • 更新树状数组时,为了减少清除的时间开销,将j/d放入,代表j

import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;





public class Main{
	static long md=(long)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	
	static
	class BIT{
		int size;
		int[] tr;
		public BIT(int n) {
			size=n;
			tr=new int[n+1];
		}
		int lowbit(int x) {
			return x&-x;
		}
		void update(int x) {
			for(int i=x;i<=size;i+=lowbit(i)) {
				tr[i]+=1;
			}
		}
		int query(int x) {
			int res=0;
			for(int i=x;i>0;i-=lowbit(i)) {
				res+=tr[i];
			}
			return res;
		}
		void clear(int j) {
			for(int i=1;i<=j;++i)tr[i]=0;
		}
	}
	
	
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    int[] a=new int[n+1];
	    int[] b=new int[n+1];
	    for(int i=1;i<=n;++i) {
	    	a[i]=input.nextInt();
	    	b[a[i]]=i;
	    }
	    BIT Tp=new BIT(n);
	    long[] f=new long[n+1];
	    
	    
	    for(int i=n;i>=1;--i) {
	    	int d=i;
	    	Vector<Integer> v=new Vector<Integer>();
	    	for(int k=d;k<=n;k+=d) {
	    		v.add(b[k]);
	    	}
	    	v.sort((o1,o2)->{return o1-o2;});
	    	int m=v.size();
	    	Tp.clear(m);
	    	Tp.update(a[v.get(0)]/d);
	    	for(int j=1;j<m;++j) {
	    		int N=Tp.query(m)-Tp.query(a[v.get(j)]/d);
	    		f[d]+=N;
	    		Tp.update(a[v.get(j)]/d);
	    	}
	    	for(int k=2*d;k<=n;k+=d) {
	    		f[d]-=f[k];
	    	}
	    }
	    out.print(f[1]);
 	    out.flush();
	    out.close();
	}
	//System.out.println();
	//out.println();
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;

	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值