NC兔子的逆序对JAVA实现

题目

分析


树状数组求解逆序对,至于后面的反转区间,通过化解公式可知与(R-L+1)*(R-L)/2的奇偶有关

先求解总的逆序对,求法很多我用的数组数组,通过求出顺序对,然后和总序对相减求出总的逆序对。

反转区间,可以看出它不影响反转区间之外的逆序对,只会影响内部。
通过公式 总序对=逆序对+顺序对 可知 ,假设此区间左右区间端点为L,R,区间的逆序对为X,而总序对可知为(R-L+1)(R-L)/2)。
如果反转,逆序对变为(R-L+1)
(R-L)/2)-X.与之前逆序对数相差(R-L+1)(R-L)/2)-2X。然后看本题只考虑反转之后总的逆序对数的奇偶性,可知相差的2*X对答案不影响,有影响的只有 (R-L+1)(R-L)/2

PS:此题需要加下快读快输

代码


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class 兔子的逆序对 {
	static int n;
	static long ans,su;
	static int nod[];
	public static void main(String[] args) {
		n=sc.nextInt();nod=new int[n+1];
		ans=(long)n*(n-1)/2;su=0;
		int x;
		for (int i =1; i <=n; i++) {
			x=sc.nextInt();
			su+=query(x);update(x);//先查询这个数能产生的顺序对数量,然后放入数组中
		}
		ans-=su;ans%=2;//得到逆序对数,后面只考虑奇偶性了
		int m=sc.nextInt();
		int l,r;
		for (int i =1; i <=m; i++) {
			l=sc.nextInt();r=sc.nextInt();
			ans+=(r-l+1)*(r-l)/2;
			if((ans=ans%2)==0) {
				out.println("like");
			}else {
				out.println("dislike");
			}
		}
		out.flush();
	}
	//----------------树状数组模板----------------------
	public static int lowbit(int x) {
		return x&(-x);
	}
	public static void update(int x) {
		for (int i =x; i <=n; i+=lowbit(i)) {
			nod[i]+=1;
		}
	}
	public static int query(int x){
		int sum=0;
		for (int i =x; i>0;i-=lowbit(i)) {
			sum+=nod[i];
		}
		return sum;
	}
	//-----------------------------------------------------------
	static class FastScanner{//用于快速读入大量数据
		BufferedReader br;
		StringTokenizer st;
		public FastScanner(InputStream in) {
			br = new BufferedReader(new InputStreamReader(in),16384);
			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());
		}
	}
	static FastScanner sc = new FastScanner(System.in);//快读
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));//快速输出
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值