2022年春招 360笔试 第二题 翻转棋子

这篇博客探讨了一个关于棋子翻转的问题,其中涉及n个棋子和q次区间翻转操作。作者指出,由于n的值过大,不适合使用线段树或树状数组。通过分析,发现翻转操作可以简化为对奇数位置区间的影响,并通过排序输入来统计黑色棋子数量。代码实现中,首先将输入排序,然后遍历奇数索引的区间,更新黑色棋子的总数。这是一个巧妙的解决方案,它避免了大内存消耗并保证了效率。
摘要由CSDN通过智能技术生成

        题目大致是有n个(long类型)棋子,棋子开始时全部朝上。有q次(q<300)查询输入,每次输入L,R(1<=L,R<=n)使得区间内的棋子从黑色变成白色,白色变成黑色。需要输出每次反转后有多少黑色棋子。

一、解题思路

1、看到区间修改,区间查询的题目应该直接想到线段树和树状数组。本题中的翻转操作可以转化为异或,初始全部为1(表示黑色棋子),翻转操作就是异或1。这样能够保证复杂度在nlogn。但本题中n太大,会爆内存所以肯定不是这种方法

2、求区间内有多少的问题,考虑维护前缀和(这种方法我不会)

3、同时考虑两次翻转的操作,不妨设输入为a,b,c,d且a<b<c<d。则有三种可能的情况,分别为[a.b],[c.d]、[a,c],[b,d]和[a,d],[b,c];

       如图所示,图中阴影部分是实际翻转的棋子。不难发现三种组合情况的最终结果相同。故得出结论,左端点为偶数的区间影响最终结果。

        注意到特例[1,1],[2.2](区间重合)的问题,左右端点相同对结果的贡献应当为1+1=2,而不是0。观察发现将左端点减一即可。

        将所有输入排序,取出奇数段的长度进行统计。

二、AC代码

import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		int q = sc.nextInt();
		ArrayList<Long> list = new ArrayList<>();
		for(int i=0;i<q;++i) {
			long l=sc.nextLong();
			long r=sc.nextLong();
			l = l-1;//控制端点,比如1,1和2,2的用例
			list.add(l);
			list.add(r);
			Collections.sort(list);//构造扫描线
			long ans = n;
			int size=list.size();
			for(int j=0;j<size-1;++j)
			{
				if(j%2==0)//奇数段才会影响结果
				{
					long tmp = list.get(j+1)-list.get(j);
					ans-=tmp;
				}
			}
			System.out.println(ans);
		}
		sc.close();
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值